Javascript 如何根据某些条件对数组进行部分排序?
如何根据我选择的一些条件对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
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
对性能有很大影响-事实上,缓存甚至可能是有害的。我想当实际改变数组时,它可能会改变一些东西,但我也认为这与拼接
本身无关。不管怎样,这并不是说我们有其他选择。。。