Javascript Javascript按两个字段对数组进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6129952/
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-08-23 20:21:59  来源:igfitidea点击:

Javascript sort array by two fields

javascriptarrays

提问by Mark

grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);      
    return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;
});

So the above code sorts the array by gsize - smallest to largest. It works good. But if the gsize is the same I would like it to then sort by glow.

所以上面的代码按 gsize 对数组进行排序 - 从最小到最大。它运作良好。但如果 gsize 相同,我希望它按发光排序。

Thanks.

谢谢。

回答by anmorozov23

grouperArray.sort(function (a, b) {   
    return a.gsize - b.gsize || a.glow - b.glow;
});

shorter version

较短的版本

回答by Chris Eberle

grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);

    if(aSize == bSize)
    {
        return (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0;
    }
    else
    {
        return (aSize < bSize) ? -1 : 1;
    }
});

回答by Vinorth

grouperArray.sort((a, b) => a.gsize - b.gsize || a.glow - b.glow);

Even shorter version using arrow syntax!

使用箭头语法的更短版本!

回答by nihlton

I realize this was asked some time ago, but I thought I would add my solution.

我意识到这是前一段时间被问到的,但我想我会添加我的解决方案。

This function generates sort methods dynamically. simply supply each sortable child property name, prepended with +/- to indicate ascending or descending order. Super re-usable, and it doesn't need to know anything about the data structure you've put together. Could be made idiot proof - but doesn't seem necessary.

此函数动态生成排序方法。只需提供每个可排序的子属性名称,加上 +/- 以指示升序或降序。超级可重用,它不需要知道你放在一起的数据结构。可以证明白痴 - 但似乎没有必要。

function getSortMethod(){
    var _args = Array.prototype.slice.call(arguments);
    return function(a, b){
        for(var x in _args){
            var ax = a[_args[x].substring(1)];
            var bx = b[_args[x].substring(1)];
            var cx;

            ax = typeof ax == "string" ? ax.toLowerCase() : ax / 1;
            bx = typeof bx == "string" ? bx.toLowerCase() : bx / 1;

            if(_args[x].substring(0,1) == "-"){cx = ax; ax = bx; bx = cx;}
            if(ax != bx){return ax < bx ? -1 : 1;}
        }
    }
}

example usage:

用法示例:

items.sort(getSortMethod('-price', '+priority', '+name'));

items.sort(getSortMethod('-price', '+priority', '+name'));

this would sort itemswith lowest pricefirst, with ties going to the item with the highest priority. further ties are broken by the item name

这将首先items以最低的方式排序price,关系将指向具有最高的项目priority。进一步的联系被项目打破name

where items is an array like:

其中 items 是一个数组,如:

var items = [
    { name: "z - test item", price: "99.99", priority: 0, reviews: 309, rating: 2 },
    { name: "z - test item", price: "1.99", priority: 0, reviews: 11, rating: 0.5 },
    { name: "y - test item", price: "99.99", priority: 1, reviews: 99, rating: 1 },
    { name: "y - test item", price: "0", priority: 1, reviews: 394, rating: 3.5 },
    { name: "x - test item", price: "0", priority: 2, reviews: 249, rating: 0.5 } ...
];

live demo: http://gregtaff.com/misc/multi_field_sort/

现场演示:http: //gregtaff.com/misc/multi_field_sort/

EDIT: Fixed issue with Chrome.

编辑:修复了 Chrome 的问题。

回答by John Green

I expect the ternaryoperator ((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;)has you confused. You should check out the link to understand it better.

我希望三元运算符((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;)让您感到困惑。您应该查看链接以更好地理解它。

Until then, here's your code blown out into full if/else.

在那之前,这里是你的 if/else 代码。

grouperArray.sort(function (a, b) {
    if (a.gsize < b.gsize)
    {
        return -1;
    }
    else if (a.gsize > b.gsize)
    {
        return 1;
    }
    else
    {
        if (a.glow < b.glow)
        {
            return -1;
        }
        else if (a.glow > b.glow)
        {
            return 1;
        }
        return 0;
    }
});

回答by The_Black_Smurf

Here's an implementation for those who may want something more generic that would work with any number of fields.

对于那些可能想要更通用的东西来处理任意数量的字段的人来说,这是一个实现。

Array.prototype.sortBy = function (propertyName, sortDirection) {

    var sortArguments = arguments;
    this.sort(function (objA, objB) {

        var result = 0;
        for (var argIndex = 0; argIndex < sortArguments.length && result === 0; argIndex += 2) {

            var propertyName = sortArguments[argIndex];
            result = (objA[propertyName] < objB[propertyName]) ? -1 : (objA[propertyName] > objB[propertyName]) ? 1 : 0;

            //Reverse if sort order is false (DESC)
            result *= !sortArguments[argIndex + 1] ? 1 : -1;
        }
        return result;
    });

}

Basically, you may specify any number of property name / sort direction:

基本上,您可以指定任意数量的属性名称/排序方向:

var arr = [{
  LastName: "Doe",
  FirstName: "John",
  Age: 28
}, {
  LastName: "Doe",
  FirstName: "Jane",
  Age: 28
}, {
  LastName: "Foo",
  FirstName: "John",
  Age: 30
}];

arr.sortBy("LastName", true, "FirstName", true, "Age", false);
//Will return Jane Doe / John Doe / John Foo

arr.sortBy("Age", false, "LastName", true, "FirstName", false);
//Will return John Foo / John Doe / Jane Doe

回答by Benjamin Portman

Here is an implementation that uses recursion to sort by any number of sort fields from 1 to infinite. You pass it a results array which is an array of result objects to sort, and a sorts array which is an array of sort objects defining the sort. Each sort object must have a "select" key for the key name that it sorts by and an "order" key which is a string indicating "ascending" or "descending".

这是一个实现,它使用递归按从 1 到无限的任意数量的排序字段进行排序。你传递给它一个结果数组,它是一个要排序的结果对象数组,一个 sorts 数组是一个定义排序的排序对象数组。每个排序对象都必须有一个用于排序的键名的“选择”键和一个“排序”键,它是一个指示“升序”或“降序”的字符串。

sortMultiCompare = (a, b, sorts) => {
    let select = sorts[0].select
    let order = sorts[0].order
    if (a[select] < b[select]) {
        return order == 'ascending' ? -1 : 1
    } 
    if (a[select] > b[select]) {
        return order == 'ascending' ? 1 : -1
    }
    if(sorts.length > 1) {
        let remainingSorts = sorts.slice(1)
        return this.sortMultiCompare(a, b, remainingSorts)
    }
    return 0
}

sortResults = (results, sorts) => {
    return results.sort((a, b) => {
        return this.sortMultiCompare(a, b, sorts)
    })
}

// example inputs
const results = [
    {
        "LastName": "Doe",
        "FirstName": "John",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Doe",
        "FirstName": "Jane",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Johnson",
        "FirstName": "Kevin",
        "MiddleName": "Bill"
    }
]

const sorts = [
    {
        "select": "LastName",
        "order": "ascending"
    },
    {
        "select": "FirstName",
        "order": "ascending"
    },
    {
        "select": "MiddleName",
        "order": "ascending"
    }    
]

// call the function like this:
let sortedResults = sortResults(results, sorts)

回答by silex

grouperArray.sort(function (a, b) {
  var aSize = a.gsize;
  var bSize = b.gsize;
  var aLow = a.glow;
  var bLow = b.glow;
  console.log(aLow + " | " + bLow);      
  return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : ( (aLow < bLow ) ? -1 : (aLow > bLow ) ? 1 : 0 );
});

回答by Tim Williams

grouperArray.sort(function (a, b) {
     var aSize = a.gsize;     
     var bSize = b.gsize;     
     var aLow = a.glow;
     var bLow = b.glow;
     console.log(aLow + " | " + bLow);
     return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0); }); 

回答by Deliaz

Here is the solution for the case, when you have a priority sort key, which might not exist in some particular items, so you have to sort by fallback keys.

这是这种情况的解决方案,当您有一个优先排序键时,它可能不存在于某些特定项目中,因此您必须按回退键排序。

An input data example (id2is priority sort key):

输入数据示例(id2是优先排序键):

const arr = [
    {id: 1},
    {id: 2, id2: 3},
    {id: 4},
    {id: 3},
    {id: 10, id2: 2},
    {id: 7},
    {id: 6, id2: 1},
    {id: 5},
    {id: 9, id2: 2},
    {id: 8},
];

And the output should be:

输出应该是:

[ { id: 6, id2: 1 },
  { id: 9, id2: 2 },
  { id: 10, id2: 2 },
  { id: 2, id2: 3 },
  { id: 1 },
  { id: 3 },
  { id: 4 },
  { id: 5 },
  { id: 7 },
  { id: 8 } ]

The comparator function will be like:

比较器函数将类似于:

arr.sort((a,b) => {
  if(a.id2 || b.id2) {
    if(a.id2 && b.id2) {
      if(a.id2 === b.id2) {
        return a.id - b.id;
      }
      return a.id2 - b.id2;
    }
    return a.id2 ? -1 : 1;
  }
  return a.id - b.id
});

P.S. In case if .idof .id2can be zeros, consider to use typeof.

PS在情况下,如果.ID.id2可以为零,可以考虑使用typeof