Javascript 对数组进行排序,使其在数组中首先具有特定项
我有这样一个数组:Javascript 对数组进行排序,使其在数组中首先具有特定项,javascript,arrays,sorting,Javascript,Arrays,Sorting,我有这样一个数组: [{flag: true, other: 1}, {flag: true, other: 2}, {flag: false, other: 3}, {flag: true, other: 4}, {flag: true, other: 5}, {flag: true, other: 6}, {flag: false, other: 7}] 我想要这个: [{flag: false, other: 3}, {flag: false, other: 7}, {f
[{flag: true, other: 1},
{flag: true, other: 2},
{flag: false, other: 3},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6},
{flag: false, other: 7}]
我想要这个:
[{flag: false, other: 3},
{flag: false, other: 7},
{flag: true, other: 1},
{flag: true, other: 2},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6}]
基本上,我希望如果数组[2].flag===false(或我选择的任何其他值),匹配的元素将被放在数组的第一位,但在前面的匹配元素之后。
不匹配的元素保持原来的顺序
外观的顺序很重要
如何在JavaScript中做到最好?编写一个自定义排序函数,并使用该标志提高优先级:
array.sort(function(a,b) {
if (!a['flag'] && b['flag'])
return 1;
if (a['flag'] && !b['flag'])
return -1;
return a['other'] - b['other']
});
基本上,我假设列表中设置了标志的条目优先于没有标志的条目。因此,如果a没有该标志,而b有,则返回1(选择b)。如果a返回a,b不返回a
在两者都设置了标志或都没有设置标志的情况下,cmp是正常的。排序方法可以使用可选的sort函数作为参数,您可以使用该参数定义排序后元素的顺序
arr=arr.sort(函数(a,b){//使用自定义函数对数组进行排序,
//它被多次称为
//确定新的顺序。a和b是两个
//元素进行比较。JavaScript使用
//用于确定新订单的返回值:
//1-a应该比b来得晚
//-1-a应该比b来得早
//0-它们应保持当前顺序
返回a.flag==true&&b.flag==false
?1//如果a为真,b为假,则a应随后出现
:a.flag==false&&b.flag==true
?-1//如果a为假,b为真,则a应提前到来
:a.其他>b.其他
?1//如果a.other>b.other,a必须稍后再来
:a.其他
这实际上不是排序。您可以在阵列中循环两次,然后构建一个新阵列:
var result = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i].flag === false) {
result.push(arr[i]);
}
}
for (var i = 0; i < arr.length; i++) {
if (!arr[i].flag === false) {
result.push(arr[i]);
}
}
var结果=[];
对于(变量i=0;i
您还可以使用两个结果数组和一个循环,并连接结果:
var result1 = [], result2 = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i].flag === false) {
result1.push(arr[i]);
} else {
result2.push(arr[i]);
}
}
var result = result1.concat(result2);
var result1=[],result2=[];
对于(变量i=0;i
由于要选择某些数组项,但要保持它们的原始顺序,因此需要使用filter()
方法。此函数是一个,因此您可能需要使用该页面提供的垫片,具体取决于您支持的浏览器
(当我第一次阅读您的问题时,我认为您希望根据标志进行排序,然后根据值进行排序;为此,您可以使用内置的sort()
方法。)
我觉得这有点简单。
因为javascript将true视为1,将false视为0,所以可以使用它们来创建这样的比较器
var comp = function(a,b){
return a.flag*1 - b.flag*1;
}
然后你可以用这个比较器对数组进行排序
var arr = [{flag: true, other: 1},
{flag: true, other: 2},
{flag: false, other: 3},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6},
{flag: false, other: 7}];
arr.sort(comp);
ECMAScript 6引入的方法(例如,[…对象]
)使用数组的reduce
方法使这一点相对简单:
const arr = [
{ flag: true, other: 1 },
{ flag: true, other: 2 },
{ flag: false, other: 3 },
{ flag: true, other: 4 },
{ flag: true, other: 5 },
{ flag: true, other: 6 },
{ flag: false, other: 7 }
];
const sortedArr = arr.reduce((acc, element) => {
if (!element.flag) {
return [element, ...acc];
}
return [...acc, element];
}, []);
我发现这非常有用。一种更简单、更优雅的方法是通过两次过滤旧数组来构建一个新数组:一次按标记:true
过滤,一次按标记:false
过滤。总的来说,它看起来像:
// THE INITIAL ARRAY:
const originalArray = [
{flag: true, other: 1},
{flag: true, other: 2},
{flag: false, other: 3},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6},
{flag: false, other: 7}
];
// THE SORTED ARRAY:
const sortedArray = [
...originalArray.filter(({flag}) => flag),
...originalArray.filter(({flag}) => !flag)
];
在我看来,它比使用比较器或减缩器函数更容易让人阅读,而且(基于测量),它也是一个性能相当好的解决方案
性能比较:
我看到使用arr.reduce()
比这个解决方案执行速度慢20倍左右。我用它来做比较,你也可以自己测试一下
测量数组.reduce()
方式:
测量array.filter()
方式:
一种解决方案是根据标志
对数组排序,然后根据其他
var a=[{flag:true,other:1},
{flag:true,other:2},
{flag:false,other:3},
{flag:true,other:4},
{flag:true,other:5},
{flag:true,other:6},
{flag:false,other:7}];
a、 排序((a,b)=>a.flag-b.flag)。排序((a,b)=>a.other-b.other)代码>您可以使用值的增量进行排序
按标志排序
。如果true
或0
,如果false,布尔值将转换为1
。
按其他
排序
var数组=[{flag:true,other:1},{flag:true,other:2},{flag:false,other:3},{flag:true,other:4},{flag:true,other:5},{flag:true,other:6},{flag:false,other:7}];
array.sort((a,b)=>
a、 旗帜-b旗||
a、 其他的
);
console.log(数组)代码>
。作为控制台包装{max height:100%!important;top:0;}
对于false
的标记的元素,相对于彼此的顺序如何?@amn:它们是“前缀”的顺序数组的顺序应该是它们在原始数组中遇到的顺序。@amn:问题表明,与条件不匹配的元素的顺序与原始的顺序相同,我假设它也适用于与条件匹配的元素。@Guffa是,这个问题已经被编辑以解决我的合理顾虑:-),但同时也添加了许多好的答案,所以我退出…reduce方法是否缺少第二个参数(initialValue)?,在本例中是一个空数组。这不应该吗<代码>arr.reduce
const arr = [
{ flag: true, other: 1 },
{ flag: true, other: 2 },
{ flag: false, other: 3 },
{ flag: true, other: 4 },
{ flag: true, other: 5 },
{ flag: true, other: 6 },
{ flag: false, other: 7 }
];
const sortedArr = arr.reduce((acc, element) => {
if (!element.flag) {
return [element, ...acc];
}
return [...acc, element];
}, []);
// THE INITIAL ARRAY:
const originalArray = [
{flag: true, other: 1},
{flag: true, other: 2},
{flag: false, other: 3},
{flag: true, other: 4},
{flag: true, other: 5},
{flag: true, other: 6},
{flag: false, other: 7}
];
// THE SORTED ARRAY:
const sortedArray = [
...originalArray.filter(({flag}) => flag),
...originalArray.filter(({flag}) => !flag)
];
const arr = [
{ flag: true, other: 1 },
{ flag: true, other: 2 },
{ flag: false, other: 3 },
{ flag: true, other: 4 },
{ flag: true, other: 5 },
{ flag: true, other: 6 },
{ flag: false, other: 7 }
];
// Lets multiple the array items 11 times to increase the looping process:
new Array(11).fill().forEach(x => arr.push(...arr));
console.time();
const reducedArr = arr.reduce((acc, element) => {
if (element.flag === false) {
return [element, ...acc];
}
return [...acc, element];
}, []);
console.timeEnd(); // RESULTS: between 285-350ms
const arr = [
{ flag: true, other: 1 },
{ flag: true, other: 2 },
{ flag: false, other: 3 },
{ flag: true, other: 4 },
{ flag: true, other: 5 },
{ flag: true, other: 6 },
{ flag: false, other: 7 }
];
// Lets multiple the array items 11 times to increase the looping process:
new Array(11).fill().forEach(x => arr.push(...arr));
console.time();
const rebuiltArray = [
...arr.filter(x => !!x.flag),
...arr.filter(x => !x.flag)
];
console.timeEnd(); // RESULTS: between 6-20ms