我有一个JavaScript对象数组:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

如何在JavaScript中按last_nom的值对它们进行排序?

我知道排序(a,b),但这似乎只适用于字符串和数字。是否需要向对象添加toString()方法?


当前回答

您还可以创建一个动态排序函数,根据传递的值对对象进行排序:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        /* next line works with strings and numbers, 
         * and you may want to customize it to your needs
         */
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

所以你可以有一个这样的对象数组:

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

…当你这样做时,它会起作用:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

事实上,这已经回答了问题。下面的部分是因为许多人联系我,抱怨它不适用于多个参数。

多个参数

您可以使用下面的函数生成具有多个排序参数的排序函数。

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

这将使您能够执行以下操作:

People.sort(dynamicSortMultiple("Name", "-Surname"));

子类化数组

对于我们中能够使用ES6的幸运者,ES6允许扩展本机对象:

class MyArray extends Array {
    sortBy(...args) {
        return this.sort(dynamicSortMultiple(...args));
    }
}

这将实现:

MyArray.from(People).sortBy("Name", "-Surname");

其他回答

您也可以使用自定义toString()方法(由默认比较函数调用)创建对象类型,而不是使用自定义比较函数:

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();

使用原型继承简单快速地解决此问题:

Array.prototype.sortBy = function(p) {
  return this.slice(0).sort(function(a,b) {
    return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
  });
}

示例/用法

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]

更新:不再修改原始数组。

此排序功能可用于所有对象排序:

对象deepObject(深度对象)数字数组

您还可以通过传递1,-1作为参数进行升序或降序排序。

Object.defineProperty(Object.prototype,'deepVal'{可枚举:false,可写:true,值:函数(propertyChain){var level=propertyChain.split('.');父项=此项;对于(var i=0;i<levels.length;i++){if(!parent[levels[i]])返回未定义;parent=父[级别[i]];}返回父项;}});函数dynamicSortAll(属性,sortOrders=1){/**默认排序为升序。如果你需要按降序排序传递-1作为参数**/var sortOrder=sortOrders;返回函数(a,b){var result=(属性?((a.deepVal(属性)>b.deepVal(属性))?1:(a.deepVal(属性)<b.deepVal(属性))-1:0):((a>b)?1:(a<b)-1 : 0))返回结果*sortOrder;}}深度对象=[{a: {a:1,b:2,c:3},b: {a:4,b:5,c:6}},{a: {a:3,b:2,c:1},b: {a:6,b:5,c:4}}];let deepobjResult=deepObj.sort(dynamicSortAll('a.a',1))console.log('deepobjResult:'+JSON.stringify(deepojResult))变量obj=[{first_nom:'Lazslo',last_nom:'Jamf'},{first_nom:'猪',last_nom:'Bodine'},{first_nom:'海盗',last_nom:'Prentice'}];let objResult=obj.sort(dynamicSortAll('last_nom',1))console.log('objResult:'+JSON.stringify(objResult))var numericObj=[1,2,3,4,5,6]let numResult=numericObj.sort(dynamicSortAll(null,-1))console.log('numResult:'+JSON.stringify(numResult))let stringSortResult='helloworld'.split('').sort(dynamicSortAll(null,1))console.log('stringSortResult:'+JSON.stringify(stringSortResult))let uniqueStringOrger=[…new Set(stringSortResult)];console.log('uniqueStringOrger:'+JSON.stringify(uniqueStringOrger))

它对我有用。在这里,它将一直保持未定义状态。

函数排序(项、属性、方向){函数比较(a,b){if(!a[property]&&!b[property]){返回0;}否则如果(a[property]&&!b[property]){返回-1;}否则如果(!a[property]&&b[property]){返回1;}其他{const value1=a[property].toString().toUpperCase();//忽略大小写const value2=b[property].toString().toUpperCase();//忽略大小写如果(值1<值2){返回方向==0-1 : 1;}否则如果(值1>值2){返回方向==0?1 : -1;}其他{返回0;}}}返回项目。排序(比较);} 变量项=[{名称:'Edward',值:21},{name:“Sharpe”,值:37},{name:“And”,值:45},{name:“The”,值:-12},{名称:未定义,值:-12},{name:“Magnetic”,值:13},{name:“Zeros”,值:37}];console.log('场景顺序:-');console.log(排序(项,'name',0));console.log('下订单:-');console.log(排序(项,'name',1));

如果您有嵌套对象

const objs = [{
        first_nom: 'Lazslo',
        last_nom: 'Jamf',
        moreDetails: {
            age: 20
        }
    }, {
        first_nom: 'Pig',
        last_nom: 'Bodine',
        moreDetails: {
            age: 21
        }
    }, {
        first_nom: 'Pirate',
        last_nom: 'Prentice',
        moreDetails: {
            age: 22
        }
    }];

nestedSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
        const a = prop2 ? e1[prop1][prop2] : e1[prop1],
            b = prop2 ? e2[prop1][prop2] : e2[prop1],
            sortOrder = direction === "asc" ? 1 : -1
        return (a < b) ? -sortOrder : (a > b) ? sortOrder : 0;
    }

并称之为

objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));