javascript 对数组进行排序以在数组中首先包含特定项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6974069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 22:33:00  来源:igfitidea点击:

Sort an array to have specific items first in the array

javascriptarrayssorting

提问by DLeonardi

I've got an array as such:

我有一个这样的数组:

[{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}]

I want to have this:

我想要这个:

[{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}]

Basically I want that if array[2].flag === false(or any other value I choose) the matching element gets placed first in the array, but after previous matching elements. The elements that do not match, remain in the same order they were in originally.

基本上我希望如果array[2].flag === false(或我选择的任何其他值)匹配元素首先放置在数组中,但在之前的匹配元素之后。不匹配的元素保持它们原来的顺序。

Order of appearance is important.

出场顺序很重要。

How to do this best in JavaScript?

如何在 JavaScript 中做到最好?

采纳答案by Guffa

This isn't actually sorting. You can just loop through the array twice and build a new array:

这实际上不是排序。您可以循环遍历数组两次并构建一个新数组:

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

You can also do it with two result arrays and one loop, and concatenate the results:

你也可以用两个结果数组和一个循环来完成,并连接结果:

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

回答by felguerez

The Spread syntaxintroduced with ECMAScript6 (e.g., ...object) makes this relatively straightforward using an Array's reducemethod:

ECMAScript6 引入的Spread 语法(例如,...object)使用 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 }
];

const sortedArr = arr.reduce((acc, element) => {
  if (element.flag === false) {
    return [element, ...acc];
  }
  return [...acc, element];
}, []);

I found this example of extended parameter handlingreally helpful.

我发现这个扩展参数处理的例子真的很有帮助。

回答by Rob Osborne

Write a custom sort function and uses the flag to increase the priority:

编写自定义排序函数并使用标志来提高优先级:

array.sort(function(a,b) {
  if (!a['flag'] && b['flag'])
    return 1;
  if (a['flag'] && !b['flag'])
    return -1;
  return a['other'] - b['other']
});

Basically, I'm assuming that an entry in the list with the flag set takes priority over an item without the flag. So if a doesn't have the flag and b does, return 1 (select b). If a does and b doesn't return a.

基本上,我假设列表中设置了标志的条目优先于没有标志的项目。因此,如果 a 没有标志而 b 有标志,则返回 1(选择 b)。如果 a 和 b 不返回 a。

In the case where both have the flag set or both don't, cmp as normal.

如果两者都设置了标志或都没有设置标志,则照常进行 cmp。

回答by tiran

I think this is a little simple. Because javascript treats true as 1 and false as 0 you can use them to create a comparator like this,

我觉得这有点简单。因为 javascript 将 true 视为 1,将 false 视为 0,所以您可以使用它们来创建这样的比较器,

var comp = function(a,b){
    return a.flag*1 - b.flag*1;
}

and then you can use this comparator to sort the array

然后你可以使用这个比较器对数组进行排序

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

回答by bdesham

Since you want to select certain array items but keep them in their original order, you want the filter()method. This function is an extension to the standard, so you may need to use the shim provided at that page depending on what browsers you're supporting.

由于您想选择某些数组项但保持它们的原始顺序,因此您需要该filter()方法。此功能是标准扩展,因此您可能需要使用该页面提供的垫片,具体取决于您支持的浏览器。

(When I first read your question I thought that you wanted to sort based on the flag, and then based on value; for that you could use the built-in sort()method.)

(当我第一次阅读您的问题时,我认为您想根据标志进行排序,然后根据值进行排序;为此,您可以使用内置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);

回答by Biró Norbi

The solution:

解决方案:

A simpler and more elegant way to do is by building a new array containing the content of the old array two times: once filtered by flag: trueand once by flag: false. All together it would look like:

一种更简单、更优雅的方法是构建一个包含旧数组内容的新数组两次:一次过滤器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)
];

In my opinion it is nice-to-read and (based on my measurements) a pretty well-performing solution.

在我看来,它很好读并且(根据我的测量)是一个性能非常好的解决方案。



A performance comparison:

性能对比:

I saw that the most upvoted answerusing arr.reduce()performs around 20x slower than my solution. I used ES6 Consolefor comparison, feel free to test yourself too!

我看到的最upvoted答案使用arr.reduce()进行20倍左右比我的解决方案慢。我使用ES6 Console进行比较,您也可以自行测试!

Measuring the most upvoted array.reduce()way:

衡量最受好评的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

Measuring my array.filter()way:

测量我的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

回答by Rahul Dwivedi

One solution can be to sort the array on the basis of flagand then by the other

一种解决方案可以是根据,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);

回答by parapura rajkumar

The sort method can take an optional sortFunction as a parameter that you can use to define the ordering of elements after the sort

sort 方法可以将可选的 sortFunction 作为参数,您可以使用它来定义排序后元素的顺序

http://www.w3schools.com/jsref/jsref_sort.asp

http://www.w3schools.com/jsref/jsref_sort.asp

回答by pimvdb

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