Javascript 如何根据某些条件对数组进行部分排序?

Javascript 如何根据某些条件对数组进行部分排序?,javascript,arrays,sorting,Javascript,Arrays,Sorting,如何根据我选择的一些条件对JavaScript中的数组进行部分排序 给定一个数组 var tab = [ {html: 'This is a test'}, {html: 'Locked item', locked: true}, {html: 'Another item'}, {html: 'Another one'} //and 100 more items... ]; 第二项称为“锁定”,数组排序后,它应保持在同一位置(第二位置) var tab

如何根据我选择的一些条件对JavaScript中的数组进行部分排序

给定一个数组

var tab = [
    {html: 'This is a test'},
    {html: 'Locked item', locked: true},
    {html: 'Another item'},
    {html: 'Another one'}
    //and 100 more items...
];
第二项称为“锁定”,数组排序后,它应保持在同一位置(第二位置)

var tab = [
    {html: 'Another item'},
    {html: 'Locked item', locked: true},
    {html: 'Another one'},
    {html: 'This is a test'},
    //and 100 more items...
];
这是我目前拥有的完整代码:

var tab = [
    {html: 'This is a test'},
    {html: 'Locked item', locked: true},
    {html: 'Another item'},
    {html: 'Another one'}
    //and more items...
];

tab.sort(function(a,b){
    var aVal = a.html.toLowerCase();
    var bVal = b.html.toLowerCase();
    if (aVal===bVal)
        return 0;
    else
        return aVal < bVal ? -1 : 1;

    //how to handle locked items?
});

//desire output
/*var tab = [
    {html: 'Another item'},
    {html: 'Locked item', locked: true},
    {html: 'Another one'},
    {html: 'This is a test'},
    //and more items...
];*/

console.log(tab);
var选项卡=[
{html:'这是一个测试'},
{html:'Locked item',Locked:true},
{html:'另一项'},
{html:'另一个'}
//还有更多的项目。。。
];
tab.排序(功能(a、b){
var aVal=a.html.toLowerCase();
var bVal=b.html.toLowerCase();
如果(aVal==bVal)
返回0;
其他的
返回aVal
请参见

,这部分起作用:

tab.sort(function(a,b){
    if(a.locked || b.locked)
        return 0;
    if (a.html < b.html)
        return -1;
    if (a.html > b.html)
        return 1;
    return 0;
});
tab.排序(函数(a,b){
如果(a.锁定| | b.锁定)
返回0;
if(a.htmlb.html)
返回1;
返回0;
});
唯一的问题是,由于
sort
使用的排序算法的工作方式,它无法移动锁定项目后的第一个项目。但是,它会对示例中的最后2+项进行排序


要使其按您想要的方式工作,最好的办法是从数组中提取锁定的元素,将其索引保存在变量中,对数组进行排序,然后再次插入元素。

或者,您可以过滤掉所有锁定的项,将它们放在一个单独的数组中,如下所示:

[
    { obj: ..., index: ...}, 
    { ... }
] 
这将保留每个对象的索引。然后你可以在分类后把它们放进去。看起来有点麻烦


查看筛选,但要注意,如果没有polyfill,它在IE8中不起作用。

可能会得到优化,但是删除所有锁定的项并存储它们的初始位置,然后将它们重新添加到排序数组中应该会起作用:

var tab = [
    {html: 'This is a test'},
    {html: 'Locked item', locked: true},
    {html: 'Another item'},
    {html: 'Another one'}
    //and more items...
];

var stored = {}, newTab = [];
for(var i = 0, iLimit = tab.length; i < iLimit; i++) {
    if(tab[i].locked) {
        stored[i] = tab[i];
    } else {
        newTab.push(tab[i]);
    }
}

newTab.sort(function(a,b){
    var aVal = a.html.toLowerCase();
    var bVal = b.html.toLowerCase();
    if (aVal===bVal) {
        return 0;
    } else {
        return aVal < bVal ? -1 : 1;
    }
});

for(var indice in stored) {
    newTab.splice(indice, 0, stored[indice]);
}

console.log(newTab);
var选项卡=[
{html:'这是一个测试'},
{html:'Locked item',Locked:true},
{html:'另一项'},
{html:'另一个'}
//还有更多的项目。。。
];
存储的var={},newTab=[];
for(var i=0,iLimit=tab.length;i

这里的问题是
排序
用于线性排序,而不是其他。在它的范围之外使用它是不可靠的,这也是因为浏览器可以在它的执行方式上执行一些优化

因此,基本上只需对数组的一部分进行线性排序。您可以做的最好的事情是拉出锁定的元素,保留它们的索引,执行排序,并将锁定的元素放回正确的位置

var fixed = [], i;
for (i = tab.length; i--;) {
    if (tab[i].locked) {
        fixed.unshift({index: i, item: tab[i]});
        tab.splice(i, 1);
    }
}

tab.sort(...); // Perform your sort

for (i = 0; i < fixed.length; i++)
    tab.splice(fixed[i].index, 0, fixed[i].item);
var-fixed=[],i;
对于(i=tab.length;i--;){
如果(制表符[i]。已锁定){
fixed.unshift({index:i,item:tab[i]});
接头(i,1);
}
}
tab.排序(…);//各就各位
对于(i=0;i
我对执行了一个向后的
,并使用了push的unshift-istead,这是为了保持正确的索引

反向循环是因为当执行
splice
时,它会改变数组,因此对于正向循环,应相应调整
i
,以避免跳过项目。但这也会弄乱
fixed
中记录的索引。因此,我们改为执行一个反向循环,并使用
unshift
index
属性对
进行排序


请记住,
splice
有点慢,因此对于较大的阵列,您可能需要使用一些更优化的算法。如果数组中的固定元素不超过几十个,我想也没关系。

用“部分有效”的东西来回答问题有什么意义?@MaxArt:朝正确的方向轻推。此外,我还添加了一个关于如何正确操作的说明。我理解unshift的用法。请解释一下反向循环?@MaxArt:另外,正如您提到的性能,
tab.length
将在每次循环迭代之前进行评估,因此如果
tab
是一个较大的数组,也可能会影响性能。尽管这可能是一个小问题,除非根据阵列的大小预期会受到影响。我只是想提一下,以防它会产生更大的影响。@FrançoisWahl上次我检查jsperf时,在每次迭代中评估
length
对性能有很大影响-事实上,缓存甚至可能是有害的。我想当实际改变数组时,它可能会改变一些东西,但我也认为这与
拼接
本身无关。不管怎样,这并不是说我们有其他选择。。。