我有一个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()方法?


当前回答

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

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"}]

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

其他回答

这是一个简单的问题。我不知道为什么人们会有如此复杂的解决方案。

一个简单的排序函数(基于快速排序算法):

function sortObjectsArray(objectsArray, sortKey)
{
    // Quick Sort:
    var retVal;

    if (1 < objectsArray.length)
    {
        var pivotIndex = Math.floor((objectsArray.length - 1) / 2);  // Middle index
        var pivotItem = objectsArray[pivotIndex];                    // Value in the middle index
        var less = [], more = [];

        objectsArray.splice(pivotIndex, 1);                          // Remove the item in the pivot position
        objectsArray.forEach(function(value, index, array)
        {
            value[sortKey] <= pivotItem[sortKey] ?                   // Compare the 'sortKey' proiperty
                less.push(value) :
                more.push(value) ;
        });

        retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
    }
    else
    {
        retVal = objectsArray;
    }

    return retVal;
}

使用示例:

var myArr =
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];

myArr = sortObjectsArray(myArr, 'idx');

我没有看到任何类似于我的实现。此版本基于施瓦茨变换习惯用法。

function sortByAttribute(array, ...attrs) {
  // Generate an array of predicate-objects containing
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // Schwartzian transform idiom implementation. AKA "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i])
        result = -1;
      if (o1.compareValues[i] > o2.compareValues[i])
        result = 1;
      if (result *= predicates[i].descend)
        break;
    }
    return result;
  })
  .map(item => item.src);
}

下面是如何使用它的示例:

let games = [
  { name: 'Mashraki',          rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// Sort by one attribute
console.log(sortByAttribute(games, 'name'));
// Sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

使用xPrototype的sortBy:

var o = [
  { Name: 'Lazslo', LastName: 'Jamf'     },
  { Name: 'Pig',    LastName: 'Bodine'   },
  { Name: 'Pirate', LastName: 'Prentice' },
  { Name: 'Pag',    LastName: 'Bodine'   }
];


// Original
o.each(function (a, b) { console.log(a, b); });
/*
 0 Object {Name: "Lazslo", LastName: "Jamf"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Pirate", LastName: "Prentice"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort By LastName ASC, Name ASC
o.sortBy('LastName', 'Name').each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName ASC and Name ASC
o.sortBy('LastName'.asc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName DESC and Name DESC
o.sortBy('LastName'.desc, 'Name'.desc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pig", LastName: "Bodine"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort by LastName DESC and Name ASC
o.sortBy('LastName'.desc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pag", LastName: "Bodine"}
 3 Object {Name: "Pig", LastName: "Bodine"}
*/

给定原始示例:

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

按多个字段排序:

objs.sort(function(left, right) {
    var last_nom_order = left.last_nom.localeCompare(right.last_nom);
    var first_nom_order = left.first_nom.localeCompare(right.first_nom);
    return last_nom_order || first_nom_order;
});

笔记

a.localeCompare(b)是普遍支持的,如果a<b,a==b,a>b,则分别返回-1,0,1。||在最后一行中,last_nom优先于first_nom。减法适用于数字字段:var age_order=left.age-right.age;取反顺序,返回-last_nom_order | |-first_nom_oorder | |-age_order;

将Ege的动态解决方案与Vinay的想法相结合,您可以得到一个很好的鲁棒解决方案:

Array.prototype.sortBy=函数(){函数_sortByAttr(属性){var sortOrder=1;如果(属性[0]==“-”){sortOrder=-1;attr=attr.substr(1);}返回函数(a,b){var结果=(a[attr]<b[attr])-1:(a[attr]>b[attr])?1 : 0;返回结果*sortOrder;}}函数_getSortFunc(){if(arguments.length==0){throw“Array.sortBy()不允许零长度参数”;}var args=参数;返回函数(a,b){for(var result=0,i=0;result==0&&i<args.length;i++){result=_sortByAttr(args[i])(a,b);}返回结果;}}返回this.sort(_getSortFunc.apply(null,arguments));}用法://用于打印对象的实用程序Array.prototype.print=函数(标题){console.log(“************************************************************”);console.log(“***”+标题);console.log(“************************************************************”);对于(var i=0;i<this.length;i++){console.log(“名称:”+此[i].FirstName,此[i].LastName,“年龄:”+该[i].Age);}}//设置示例数据变量arrObj=[{名字:“Zach”,姓氏:“Emergency”,年龄:35岁},{名字:“Nancy”,姓氏:“护士”,年龄:27岁},{名字:“Ethel”,姓氏:“Emergency”,年龄:42岁},{名字:“Nina”,姓氏:“护士”,年龄:48岁},{名字:“Anthony”,姓氏:“Emergency”,年龄:44岁},{名字:“Nina”,姓氏:“护士”,年龄:32岁},{名字:“Ed”,姓氏:“Emergency”,年龄:28岁},{名字:“Peter”,姓氏:“医生”,年龄:58岁},{名字:“Al”,姓氏:“Emergency”,年龄:51岁},{名字:“Ruth”,姓氏:“注册”,年龄:62岁},{名字:“Ed”,姓氏:“Emergency”,年龄:38岁},{名字:“Tammy”,姓氏:“Triage”,年龄:29岁},{名字:“Alan”,姓氏:“Emergency”,年龄:60岁},{名字:“Nina”,姓氏:“护士”,年龄:54岁}];//单元测试arrObj.sortBy(“姓氏”).print(“姓氏升序”);arrObj.sortBy(“-姓氏”).print(“姓氏降序”);arrObj.sortBy(“姓氏”、“名字”、“年龄”).print(“姓氏升序、名字升序、年龄降序”);arrObj.sortBy(“-FirstName”,“Age”).print(“FirstName降序,Age升序”);arrObj.sortBy(“-Age”).print(“Age Descending”);