如何排序数组,但排除某些元素(保持在数组中的相同位置)

时间:2022-11-22 07:42:32

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

这将在Javascript(jQuery)中实现,但我想这个方法可以在任何语言中使用。

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.

有问题的数组是从

  • 元素列表构建的,我使用附加到列表项的.data()值作为要排序的值。

  • 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!

    4 个解决方案

    #1


    6  

    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);
      

    #2


    3  

    This should do it:

    这应该这样做:

    var sugarcontent = new Array('32','21','11','45','8','99');
    var list = $('#fruit');
    var lis = list.find('li').each(function(i,e){
       $(this).data('score',sugarcontent[i]);
    });
    var stay = lis.filter('.stay').each(function(){
        $(this).data('index',$(this).index());
    });
    lis.sort(function(a,b){
        return $(b).data('score') - $(a).data('score');
    }).appendTo(list);
    stay.each(function(){
        var index = $(this).data('index');
        if (index == 0) {
            list.prepend(this);
        } else {
            lis.filter(':eq('+index+')').insertAfter(this);
        }
    }
    

    This caches the index of the items with the class stay and then it does the sort by score and then replaces the items with the class stay back in the correct place.

    这会缓存具有类保留的项目的索引,然后按分数进行排序,然后将类替换为保留在正确位置的类。

    #3


    1  

    You're correct in thinking that the solution is generic and applicable to any development environment.

    您认为该解决方案是通用的并适用于任何开发环境是正确的。

    You'll need to partition your list of elements into two different lists - ones to be sorted, and ones to be left in place. Then, sort the first list and merge with the second.

    您需要将元素列表分为两个不同的列表 - 要排序的列表和要保留的列表。然后,对第一个列表进行排序并与第二个列表合并。

    The key problem you're facing is this: Most sort algorithms (including QuickSort, which is the most common one found in most frameworks) become quite ill-behaved if your comparison function relies on any external state (like item position).

    您面临的关键问题是:如果比较函数依赖于任何外部状态(如项目位置),则大多数排序算法(包括QuickSort,这是大多数框架中最常见的算法)变得非常不良。

    #4


    0  

    This won't work as Bevan pointed out, but I will leave it here for educational purposes:

    这不会像Bevan指出的那样有效,但我会把它留在这里用于教育目的:

    $('#fruit li').sort(function(a, b) {
        return ($(a).hasClass('stay') || $(b).hasClass('stay'))
            ? 0 : (a.data('sugar') > b.data('sugar') ? 1 : -1);
    }).appendTo('#fruit');
    

    Note: You need to set the sugar data with 'sugar' as name argument:

    注意:您需要使用'sugar'作为name参数设置糖数据:

    .data('sugar', sugarcontent[i]);
    

    #1


    6  

    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);
      

    #2


    3  

    This should do it:

    这应该这样做:

    var sugarcontent = new Array('32','21','11','45','8','99');
    var list = $('#fruit');
    var lis = list.find('li').each(function(i,e){
       $(this).data('score',sugarcontent[i]);
    });
    var stay = lis.filter('.stay').each(function(){
        $(this).data('index',$(this).index());
    });
    lis.sort(function(a,b){
        return $(b).data('score') - $(a).data('score');
    }).appendTo(list);
    stay.each(function(){
        var index = $(this).data('index');
        if (index == 0) {
            list.prepend(this);
        } else {
            lis.filter(':eq('+index+')').insertAfter(this);
        }
    }
    

    This caches the index of the items with the class stay and then it does the sort by score and then replaces the items with the class stay back in the correct place.

    这会缓存具有类保留的项目的索引,然后按分数进行排序,然后将类替换为保留在正确位置的类。

    #3


    1  

    You're correct in thinking that the solution is generic and applicable to any development environment.

    您认为该解决方案是通用的并适用于任何开发环境是正确的。

    You'll need to partition your list of elements into two different lists - ones to be sorted, and ones to be left in place. Then, sort the first list and merge with the second.

    您需要将元素列表分为两个不同的列表 - 要排序的列表和要保留的列表。然后,对第一个列表进行排序并与第二个列表合并。

    The key problem you're facing is this: Most sort algorithms (including QuickSort, which is the most common one found in most frameworks) become quite ill-behaved if your comparison function relies on any external state (like item position).

    您面临的关键问题是:如果比较函数依赖于任何外部状态(如项目位置),则大多数排序算法(包括QuickSort,这是大多数框架中最常见的算法)变得非常不良。

    #4


    0  

    This won't work as Bevan pointed out, but I will leave it here for educational purposes:

    这不会像Bevan指出的那样有效,但我会把它留在这里用于教育目的:

    $('#fruit li').sort(function(a, b) {
        return ($(a).hasClass('stay') || $(b).hasClass('stay'))
            ? 0 : (a.data('sugar') > b.data('sugar') ? 1 : -1);
    }).appendTo('#fruit');
    

    Note: You need to set the sugar data with 'sugar' as name argument:

    注意:您需要使用'sugar'作为name参数设置糖数据:

    .data('sugar', sugarcontent[i]);