我有一个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 compare( a, b ) {
  if ( a.last_nom < b.last_nom ){
    return -1;
  }
  if ( a.last_nom > b.last_nom ){
    return 1;
  }
  return 0;
}

objs.sort( compare );

或内联(由Marco Demaio转交):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))

或简化为数字(由Andre Figueiredo转交):

objs.sort((a,b) => a.last_nom - b.last_nom); // b - a for reverse sort

其他回答

对于工作狂:

const objectSorter = (p) => (a, b) => ((a, b) => a>b ? 1 : a<b ? -1 : 0)(a[p], b[p]);
objs.sort(objectSorter('first_nom'));

在TypeScript中编程时,也可以创建动态排序函数,但在这种情况下,类型变得更加复杂。

function sortByKey<O>(key: keyof O, decending: boolean = false): (a: O, b: O) => number {
    const order = decending ? -1 : 1;
    return (a, b): number => {
        const valA = a[key];
        const valB = b[key];
        if (valA < valB) {
            return -order;
        } else if (valA > valB) {
            return order;
        } else {
            return 0;
        }
    }
}

这可以在TypeScript中使用,如下所示:

const test = [
    {
        id: 0,
    },
    {
        id: 2,
    }
]

test.sort(sortByKey('id')) // OK
test.sort(sortByKey('id1')) // ERROR
test.sort(sortByKey('')) // ERROR
function compare(propName) {
    return function(a,b) {
        if (a[propName] < b[propName])
            return -1;
        if (a[propName] > b[propName])
            return 1;
        return 0;
    };
}

objs.sort(compare("last_nom"));

这是我的看法:

order参数是可选的,对于升序,默认为“ASC”。

它适用于重音字符,并且不区分大小写。

注意:它排序并返回原始数组。

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // Remove accented and diacritics
    .replace(/[\u0300-\u036f]/g, '')    // Remove accented and diacritics
    .toLowerCase()                      // Sort will be case insensitive
  ;
}

function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a, b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

一小条

函数cleaniteToSort(str){返回str.normalize('NFD')//删除重音字符.replace(/[\u0300-\u036f]/g,“”)//删除变音符号.to小写();}函数sortByProperty(arr,property,order=“ASC”){arr.forEach((item)=>item.tempProp=消毒排序(item[property]));arr.sort((a,b)=>顺序==“ASC”?a.tempProp>b.tempProp?1:a.tempProp<b.tempProp-1 : 0:a.tempProp>b.tempProp-1:a.tempProp<b.tempProp?1 : 0);arr.forEach((item)=>删除item.tempProp);返回arr;}常量rockStars=[{name:“Axl”,姓:“Rose”},{name:“埃尔顿”,姓:“John”},{name:“Paul”,姓氏:“McCartney”},{name:“楼”,姓:“里德”},{name:“freddie”,//使用小写/大写姓氏:“mercury”},{name:“Ámy”,//也适用于重音字符姓氏:“酒庄”}];sortByProperty(rockStars,“name”);console.log(“按名称A-Z排序:”);rockStars.forEach((item)=>console.log(item.name+“”+item.lastname));sortByProperty(rockStars,“姓氏”,“DESC”);console.log(“\n按姓氏Z-A排序:”);rockStars.forEach((item)=>console.log(item.lastname+“,”+item.name));

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

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