如何在JavaScript中对具有多个字段值的对象数组进行排序

时间:2022-04-05 16:01:11

I found a great method to sort an array of objects based on one of the properties as defined at:

我找到了一个很好的方法来根据以下定义的属性之一对对象数组进行排序:

Sort array of objects by string property value in JavaScript

在JavaScript中按字符串属性值对对象数组进行排序

Using that function works perfectly for a single sort (on all browsers), and even a sort within another sort EXCEPT using Google Chrome! Here is Ege Özcan's great sort routine for arrays of objects

使用该功能可以完美地用于单一排序(在所有浏览器上),甚至可以在另一种排序中使用Google Chrome进行排序!这是EgeÖzcan对物体阵列的伟大排序程序

function dynamicSort(property) { 
    return function (a,b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}

Using an array named "Data" (of course, my array has many more object pairs)...

使用名为“Data”的数组(当然,我的数组有更多对象)...

var Data = [{Category: "Business", Value: "ABC"},{Category:"Personal", Value:"XYZ"}];

I can get a proper sort where the order is listed as all the values within each category by doing this...

通过这样做,我可以得到一个合适的排序,其中订单被列为每个类别中的所有值...

Data.sort(dynamicSort("Value"));
Data.sort(dynamicSort("Category"));

By first sorting on Value, and then by Category, my array puts all values in sorted order with all the Business-base values listed first and then all the Personal-based values. Perfect! Except in Chrome where the data is sorted properly by category, but the order of the values within each category seems rather random.

通过首先对Value进行排序,然后按类别排序,我的数组将所有值按排序顺序排列,首先列出所有业务基础值,然后列出所有基于个人的值。完善!除了在Chrome中,数据按类别正确排序,但每个类别中的值的顺序似乎相当随机。

Does any one know of a better way to do a sort within a sort that would also work in Chrome?

有没有人知道在Chrome中进行排序的更好方法?

5 个解决方案

#1


36  

I created a multi-parameter version of that dynamicSort function:

我创建了该dynamicSort函数的多参数版本:

function dynamicSort(property) { 
    return function (obj1,obj2) {
        return obj1[property] > obj2[property] ? 1
            : obj1[property] < obj2[property] ? -1 : 0;
    }
}

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

I created an array as follows:

我创建了一个数组如下:

var arr = [
    {a:"a",b:"a",c:"a"},
    {a:"b",b:"a",c:"b"},
    {a:"b",b:"a",c:"a"},
    {a:"b",b:"a",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"b",b:"b",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"b",b:"b",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"b",b:"b",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"c",b:"b",c:"b"},
    {a:"c",b:"c",c:"a"}
];

and it worked when I did,

我这样做的时候很有用

arr.sort(dynamicSortMultiple("c","b","a"));

And here is a working example: http://jsfiddle.net/ZXedp/

这是一个有效的例子:http://jsfiddle.net/ZXedp/

#2


5  

The easiest way to perform a Javascript Multi-Criteria Sort (or Multi-Parameter Sort), is to use .sort, concatenate the multiple parameters together, and compare the two stings.

执行Javascript Multi-Criteria Sort(或多参数排序)的最简单方法是使用.sort,将多个参数连接在一起,并比较两个stings。

For example:

例如:

data.sort(function (a, b) {

  var aConcat = a["property1"] + a["property2"];
  var bConcat = b["property1"] + b["property2"];

  if (aConcat > bConcat) {
    return 1;
  } else if (aConcat < bConcat) {
    return -1;
  } else {
    return 0;
  }

});

I've included a JsFiddle Script here: http://jsfiddle.net/oahxg4u3/6/

我在这里包含了一个JsFiddle脚本:http://jsfiddle.net/oahxg4u3/6/

#3


1  

You may also want to have a look at thenBy.js: https://github.com/Teun/thenBy.js

您可能还想看看thenBy.js:https://github.com/Teun/thenBy.js

It allows you to use the standard Array.sort, but with firstBy().thenBy().thenBy() style.

它允许您使用标准的Array.sort,但使用firstBy()。thenBy()。thenBy()样式。

#4


1  

I now this post is quite old, anyway I found it today and quoting Ege Özcan, I improved his excellent solution implementing DESC-ASC SQL-Like functionality for anyone interested (http://jsfiddle.net/ZXedp/65/):

我现在这个帖子已经很老了,无论如何我今天发现并引用了EgeÖzcan,我改进了他的优秀解决方案,为任何感兴趣的人(http://jsfiddle.net/ZXedp/65/)实现DESC-ASC SQL-Like功能:

function dynamicSortMultiple() {
    var props=[];
    /*Let's separate property name from ascendant or descendant keyword*/
    for(var i=0; i < arguments.length; i++){
        var splittedArg=arguments[i].split(/ +/);
        props[props.length]=[splittedArg[0], (splittedArg[1] ? splittedArg[1].toUpperCase() : "ASC")];
    }
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length ;
        /*Cycle on values until find a difference!*/
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i][0], props[i][1])(obj1, obj2);
            i++;
        }
        return result;
    }
}

/*Base function returning -1,1,0 for custom sorting*/
function dynamicSort(property, isAscDesc) { 
    return function (obj1,obj2) {
        if(isAscDesc==="DESC"){
            return ((obj1[property] > obj2[property]) ? (-1) : ((obj1[property] < obj2[property]) ? (1) : (0)));
        }
        /*else, if isAscDesc==="ASC"*/
        return ((obj1[property] > obj2[property]) ? (1) : ((obj1[property] < obj2[property]) ? (-1) : (0)));
    }
}

call the function by something like this:

通过以下方式调用函数:

arr.sort(dynamicSortMultiple("c DESC","b Asc","a"));

#5


0  

Here is my solution. It faster than lodash's _.sortBy() multi-column sort function in about two times (see http://jsperf.com/multi-column-sort. I generate text of sorting function, then use it in standard .sort(). It works in Chrome and Firefox as well.

这是我的解决方案。它比lodash的_.sortBy()多列排序函数快了大约两倍(参见http://jsperf.com/multi-column-sort。我生成排序函数的文本,然后在标准.sort()中使用它它也适用于Chrome和Firefox。

function multiColumnSort(arr,sf) {
    var s = '';
    sf.forEach(function(f,idx) {
        s += 'if(arguments[0].'+f+'>arguments[1].'+f+')return 1;';
        s += 'else if(arguments[0].'+f+'==arguments[1].'+f+')';
        s += (idx < sf.length-1)? '{' : 'return 0';
    });
    s += Array(sf.length).join('}')+';return -1';
    return arr.sort(new Function(s));
};

#1


36  

I created a multi-parameter version of that dynamicSort function:

我创建了该dynamicSort函数的多参数版本:

function dynamicSort(property) { 
    return function (obj1,obj2) {
        return obj1[property] > obj2[property] ? 1
            : obj1[property] < obj2[property] ? -1 : 0;
    }
}

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

I created an array as follows:

我创建了一个数组如下:

var arr = [
    {a:"a",b:"a",c:"a"},
    {a:"b",b:"a",c:"b"},
    {a:"b",b:"a",c:"a"},
    {a:"b",b:"a",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"b",b:"b",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"b",b:"b",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"b",b:"b",c:"b"},
    {a:"b",b:"b",c:"a"},
    {a:"c",b:"b",c:"b"},
    {a:"c",b:"c",c:"a"}
];

and it worked when I did,

我这样做的时候很有用

arr.sort(dynamicSortMultiple("c","b","a"));

And here is a working example: http://jsfiddle.net/ZXedp/

这是一个有效的例子:http://jsfiddle.net/ZXedp/

#2


5  

The easiest way to perform a Javascript Multi-Criteria Sort (or Multi-Parameter Sort), is to use .sort, concatenate the multiple parameters together, and compare the two stings.

执行Javascript Multi-Criteria Sort(或多参数排序)的最简单方法是使用.sort,将多个参数连接在一起,并比较两个stings。

For example:

例如:

data.sort(function (a, b) {

  var aConcat = a["property1"] + a["property2"];
  var bConcat = b["property1"] + b["property2"];

  if (aConcat > bConcat) {
    return 1;
  } else if (aConcat < bConcat) {
    return -1;
  } else {
    return 0;
  }

});

I've included a JsFiddle Script here: http://jsfiddle.net/oahxg4u3/6/

我在这里包含了一个JsFiddle脚本:http://jsfiddle.net/oahxg4u3/6/

#3


1  

You may also want to have a look at thenBy.js: https://github.com/Teun/thenBy.js

您可能还想看看thenBy.js:https://github.com/Teun/thenBy.js

It allows you to use the standard Array.sort, but with firstBy().thenBy().thenBy() style.

它允许您使用标准的Array.sort,但使用firstBy()。thenBy()。thenBy()样式。

#4


1  

I now this post is quite old, anyway I found it today and quoting Ege Özcan, I improved his excellent solution implementing DESC-ASC SQL-Like functionality for anyone interested (http://jsfiddle.net/ZXedp/65/):

我现在这个帖子已经很老了,无论如何我今天发现并引用了EgeÖzcan,我改进了他的优秀解决方案,为任何感兴趣的人(http://jsfiddle.net/ZXedp/65/)实现DESC-ASC SQL-Like功能:

function dynamicSortMultiple() {
    var props=[];
    /*Let's separate property name from ascendant or descendant keyword*/
    for(var i=0; i < arguments.length; i++){
        var splittedArg=arguments[i].split(/ +/);
        props[props.length]=[splittedArg[0], (splittedArg[1] ? splittedArg[1].toUpperCase() : "ASC")];
    }
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length ;
        /*Cycle on values until find a difference!*/
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i][0], props[i][1])(obj1, obj2);
            i++;
        }
        return result;
    }
}

/*Base function returning -1,1,0 for custom sorting*/
function dynamicSort(property, isAscDesc) { 
    return function (obj1,obj2) {
        if(isAscDesc==="DESC"){
            return ((obj1[property] > obj2[property]) ? (-1) : ((obj1[property] < obj2[property]) ? (1) : (0)));
        }
        /*else, if isAscDesc==="ASC"*/
        return ((obj1[property] > obj2[property]) ? (1) : ((obj1[property] < obj2[property]) ? (-1) : (0)));
    }
}

call the function by something like this:

通过以下方式调用函数:

arr.sort(dynamicSortMultiple("c DESC","b Asc","a"));

#5


0  

Here is my solution. It faster than lodash's _.sortBy() multi-column sort function in about two times (see http://jsperf.com/multi-column-sort. I generate text of sorting function, then use it in standard .sort(). It works in Chrome and Firefox as well.

这是我的解决方案。它比lodash的_.sortBy()多列排序函数快了大约两倍(参见http://jsperf.com/multi-column-sort。我生成排序函数的文本,然后在标准.sort()中使用它它也适用于Chrome和Firefox。

function multiColumnSort(arr,sf) {
    var s = '';
    sf.forEach(function(f,idx) {
        s += 'if(arguments[0].'+f+'>arguments[1].'+f+')return 1;';
        s += 'else if(arguments[0].'+f+'==arguments[1].'+f+')';
        s += (idx < sf.length-1)? '{' : 'return 0';
    });
    s += Array(sf.length).join('}')+';return -1';
    return arr.sort(new Function(s));
};