JSFiddle - React, Tailwind, and code Playground

by Mottie

HTML

<select>
    <option value="a">a</option>
    <option value="c">c</option>
    <option value="a">a</option>
    <option value="a">a</option>
    <option value="f">f</option>
    <option value="c">c</option>
    <option value="c">c</option>
    <option value="a">a</option>
    <option value="f">f</option>
    <option value="e">e</option>
    <option value="a">a</option>
    <option value="d">d</option>
    <option value="b">b</option>
</select>

CSS

/*
- Option a: 5 times
- Option c: 3 times
- Option f: 2 times
Then we would like the select to be ordered a, c, f, b, d, e
*/

JavaScript

var indx,
    xref = {},
    newHtml = '',
    $select = $('select'),
    opts = $select.find('option')
    // build array of options & count repeats
    .map(function () {
        var v = this.value;
        if (xref[v]) {
            xref[v]++
        } else {
            xref[v] = 1;
        }
        return v;
    })
    // sort options by adding "0" or "1" in front 
    // to perform a weighted sort so duplicates get sorted first
    .sort(function(a, b){
        var x = xref[a] > 1 ? '0' + a : '1' + a,
            y = xref[b] > 1 ? '0' + b : '1' + b;
        return x === y ? 0 : x > y ? 1 : -1;
    }),
    // return unique array values
    arr = $.grep(opts, function (v, k) {
        return $.inArray(v, opts) === k;
    });

// replace current options with new list
for (indx = 0; indx < arr.length; indx++) {
    newHtml += '<option value="' + arr[indx] + '">' + arr[indx] + '</option>';
}
$select.html(newHtml);