2010-03-25 32 views
6

这将在Javascript(jQuery)中实现,但我认为该方法可以用于任何语言。如何排序数组,但排除某些元素(要保留在阵列中的相同位置)

我有一个项目的数组,我需要执行排序。 但是数组中有一些项必须保持在相同的位置(相同的索引)。

有问题的数组是从<li>元素的列表构建的,我将附加到列表项的.data()值作为要排序的值。

这里最好的方法是什么?

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

我想结果如下排序列表...

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

谢谢!

回答

6

算法是:

  • 提取和排序没有打上stay
  • 合并stay项目的项目和排序的项

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

这是最类似于我最终结果的代码,所以我标记为正确 - 我确定由petersendidit提供的解决方案也很好(虽然它未经测试)。谢谢! – calumbrodie 2010-03-30 10:47:27

0

这将无法正常工作,贝文指出的那样,但我会离开这里的教育目的:

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

注意:您需要用“糖”作为名称参数设置糖数据:

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

这种方法的问题是固定的项目成为此类障碍 - 任何低于固定点的物品将永远不会超过它,反之亦然。 – Bevan 2010-03-25 20:51:40

+0

谢谢指出语法错误,我修正了上面的示例代码。 – calumbrodie 2010-03-25 21:01:23

1

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

您需要将元素列表划分为两个不同的列表 - 要排序的元素和要排列的元素。然后,排序第一个列表并与第二个列表合并。你面对的关键问题是:大多数排序算法(包括QuickSort,这是大多数框架中最常见的算法),如果你的比较函数依赖于任何外部状态(比如项目位置),它会变得非常不正常)。

+0

我应该使用jQuery合并函数还是连接数组和度假?如何确保我的数组“固定”项目在索引相同时优先考虑?你提出的解决方案正是我第一次尝试这样做的方式,但我无法完成工作。至少我知道我在正确的轨道上。感谢您的输入! – calumbrodie 2010-03-25 20:55:52

+0

通过回答@Konstantin对我来说似乎很好(我的Javascript不能胜任任务+1) – Bevan 2010-03-26 06:24:32

3

这应做到:

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

这缓存与类住宿项目的索引,然后它的排序分数,然后替换与类的物品留在后面在正确的位置。

相关问题