Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort an array, yet exclude certain elements (to be kept at the same position in the array)

This will be implemented in Javascript (jQuery) but I suppose the method could be used in any language.

I have an array of items and I need to perform a sort. However there are some items in the array that have to be kept in the same position (same index).

The array in question is build from a list of <li> elements and I'm using .data() values attached to the list item as the value on which to sort.

What approach would be best here?

<ul id="fruit">
  <li class="stay">bananas</li>
  <li>oranges</li>
  <li>pears</li>
  <li>apples</li>
  <li class="stay">grapes</li>
  <li>pineapples</li>
</ul>

<script type="text/javascript">
    var sugarcontent = new Array('32','21','11','45','8','99');
    $('#fruit li').each(function(i,e){
       $(this).data('sugar',sugarcontent[i]);
    })
</script>

I want the list sorted with the following result...

<ul id="fruit">
      <li class="stay">bananas</li> <!-- score = 32 -->
      <li>pineapples</li> <!-- score = 99 -->
      <li>apples</li> <!-- score = 45 -->
      <li>oranges</li> <!-- score = 21 -->
      <li class="stay">grapes</li> <!-- score = 8 -->
      <li>pears</li> <!-- score = 11 -->
  </ul>

Thanks!

like image 462
calumbrodie Avatar asked Mar 25 '10 20:03

calumbrodie


1 Answers

Algorithm is:

  • Extract and sort items not marked with stay
  • Merge stay items and sorted items

    var sugarcontent = new Array(32, 21, 11, 45, 8, 99);
    
    var items = $('#fruit li');
    
    items.each(function (i) {
        $(this).data('sugar', sugarcontent[i]);
        // Show sugar amount in each item text - for debugging purposes
        if ($(this).hasClass('stay'))
            $(this).text("s " + $(this).text());
        else
            $(this).text(sugarcontent[i] + " " + $(this).text());
    });
    
    // Sort sortable items
    var sorted = $(items).filter(':not(.stay)').sort(function (l, r) {
        return $(l).data('sugar') - $(r).data('sugar');
    });
    
    // Merge stay items and sorted items
    var result = [];
    var sortedIndex = 0;
    
    for (var i = 0; i < items.length; i++)
        if (!$(items[i]).hasClass('stay')) {
            result.push(sorted[sortedIndex]);
            sortedIndex++;
        }
        else
            result.push(items[i]);
    
    // Show result
    $('#fruit').append(result);
    
like image 109
Konstantin Spirin Avatar answered Sep 29 '22 20:09

Konstantin Spirin