我有一个阵列:
[{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}]
基本上我希望如果array[2].flag === false
(或我选择的任何其他值)匹配元素首先放在数组中,但是在之前的匹配元素之后。
不匹配的元素保持原来的顺序。
外观顺序很重要。
如何在JavaScript中做到最好?
答案 0 :(得分:13)
ECMAScript6引入的Spread syntax(例如,...object
)使用数组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 === false) {
return [element, ...acc];
}
return [...acc, element];
}, []);
我发现这example of extended parameter handling非常有帮助。
答案 1 :(得分:8)
编写自定义排序函数并使用该标志来提高优先级:
array.sort(function(a,b) {
if (!a['flag'] && b['flag'])
return 1;
if (a['flag'] && !b['flag'])
return -1;
return a['other'] - b['other']
});
答案 2 :(得分:7)
这实际上并不是排序。您可以循环遍历数组两次并构建一个新数组:
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 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);
答案 3 :(得分:4)
一种更简单,更优雅的方法是通过两次构建一个包含旧数组内容的新数组:一次被flag: true
过滤,一次被flag: false
过滤。总共看起来像:
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}
];
const sortedArray = [
...originalArray.filter(({flag}) => flag),
...originalArray.filter(({flag}) => !!flag)
];
在我看来,它很容易阅读,并且(根据我的测量结果)是一种性能很好的解决方案。
我发现the most upvoted answer使用arr.reduce()
的速度比我的解决方案慢20倍。我使用ES6 Console进行比较,也可以自行测试!
array.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 }
];
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
array.filter()
方式进行测量: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 }
];
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
答案 4 :(得分:1)
我认为这有点简单。 因为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);
答案 5 :(得分:0)
sort方法可以使用一个可选的sortFunction作为参数,您可以使用它来定义排序后元素的排序
答案 6 :(得分:0)
由于您要选择某些数组项但保持其原始顺序,因此您需要filter()
方法。此功能是extension to the standard,因此您可能需要使用该页面提供的填充程序,具体取决于您支持的浏览器。
(当我第一次阅读你的问题时,我认为你想根据标志进行排序,然后根据价值进行排序;为此你可以使用内置的sort()
方法。)
var input = [{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}]
var false_items = input.filter(
function(val, idx, arr) {
return (val["flag"] == false);
});
var true_items = input.filter(
function(val, idx, arr) {
return (val["flag"] == true);
});
var sorted = false_items.concat(true_items);
答案 7 :(得分:0)
一种解决方案可以是根据flag
对数组进行排序,然后根据other
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.sort((a, b)=> a.flag - b.flag).sort((a,b) => a.other - b.other);
答案 8 :(得分:0)
您可以按值的增量进行排序。
flag
排序。如果是1
,则布尔值将转换为true
;如果是{{1},则布尔值将转换为0
false.
排序。
other
var array = [{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.flag - b.flag ||
a.other - b.other
);
console.log(array);
答案 9 :(得分:-1)
arr = arr.sort(function(a, b) { // sort the array using a custom function,
// which is called a number of times to
// determine the new order. a and b are two
// elements to compare. JavaScript uses the
// return value to determine the new order:
// 1 - a should come later than b
// -1 - a should come earlier than b
// 0 - they should stay in their current order
return a.flag === true && b.flag === false
? 1 // if a is true and b is false a should come later on
: a.flag === false && b.flag === true
? -1 // if a is false and b is true a should come earlier
: a.other > b.other
? 1 // if a.other > b.other, a must come later on
: a.other < b.other
? -1 // if a.other < b.other, a must come earlier
: 0; // otherwise they are equal, so they have no order difference
});