Javascript's sort is 'unstable' - how do I get around this?

后端 未结 1 1983
天涯浪人
天涯浪人 2020-12-19 13:27

According to the MDN spec, Javascript\'s sort() function is \'unstable\' (does not maintain input order for identical elements).

Ironically, it seems that Firefox cu

相关标签:
1条回答
  • 2020-12-19 14:15

    Here is an example of a working stable sort. It adds an extra parameter for the original item index which is used if items are otherwise "equal". The code should work in any browser in use.

    Note that it is an example only and should be modified to suit your particular circumstance.

    <script type="text/javascript">
    
    // Return the text content of an element depending on
    // whether the textContent or innerText property is supported
    function getText(el) {
      if (typeof el.textContent == 'string') {
        return el.textContent;
      } else if (typeof el.innerText == 'string') {
        return el.innerText;
      } else {
        // gather text nodes and concatenate values
        // trimmed as almost never used now
      }
    }
    
    
    function sortEm(){
    
      // Get the elements to sort
      var container = document.getElementById('container'); 
      var divs = container.getElementsByTagName('div');
      var els = [];
    
      // Convert collection to an array, add the current index for the element
      // as a data- property
      for (var i=0, iLen=divs.length; i<iLen; i++) {
        divs[i].setAttribute('data-sortIndex', i);
        els[i] = divs[i];
      }
    
      // Sort the array. If the textContent is equal, use
      // the original index
      els.sort(function(a, b) {
        var aText = getText(a);
        var bText = getText(b);
    
        if (aText < bText) return -1;
        if (aText > bText) return 1;
        return a.getAttribute('data-SortIndex') - b.getAttribute('data-sortIndex');
      })
    
      // Modify the content
      for (var j=0, jLen=els.length; j<jLen; j++) {
        container.appendChild(els[j]);
      }
    }
    
    </script>
    
    <div id="container">
      <div style="background-color: red;">0</div>
      <div style="background-color: red;">2</div>
      <div style="background-color: blue;">0</div>
    </div>
    <button onclick="sortEm()">Sort divs</button>
    

    The extra parameter is added as an attribute and could be removed when elements are added back to the container to keep things clean.

    0 讨论(0)
提交回复
热议问题