按数组中一个属性的字母顺序对对象进行排序

349

假设你有一个像这样的JavaScript类

var DepartmentFactory = function(data) {
    this.id = data.Id;
    this.name = data.DepartmentName;
    this.active = data.Active;
}

假设你创建了该类的多个实例并将它们存储在一个数组中

var objArray = [];
objArray.push(DepartmentFactory({Id: 1, DepartmentName: 'Marketing', Active: true}));
objArray.push(DepartmentFactory({Id: 2, DepartmentName: 'Sales', Active: true}));
objArray.push(DepartmentFactory({Id: 3, DepartmentName: 'Development', Active: true}));
objArray.push(DepartmentFactory({Id: 4, DepartmentName: 'Accounting', Active: true}));
所以我现在有一个由DepartmentFactory创建的对象数组。我该如何使用array.sort()方法按每个对象的DepartmentName属性对这个对象数组进行排序? array.sort()方法在对字符串数组排序时工作得非常好。
var myarray=["Bob", "Bully", "Amy"];
myarray.sort(); //Array now becomes ["Amy", "Bob", "Bully"]

但是如何让它适用于对象列表?


你可以将一个排序函数作为第一个参数传递给 .sort()。 - Paul Tomblin
2
由于您正在使用DepartmentFactory作为构造函数,请使用new DepartmentFactory创建其对象,否则数组将填充一堆undefined值。 - Anurag
14个回答

520

你需要像这样做:

objArray.sort(function(a, b) {
    var textA = a.DepartmentName.toUpperCase();
    var textB = b.DepartmentName.toUpperCase();
    return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});

注意:更改大小写(转换为大写或小写)可以确保不区分大小写排序。


7
我已经查看了你的答案50亿次,因为我总是记不住如何做这件事。 此外,我的 Linter 总是告诉我"表达式周围存在无谓的括号": return (textA < textB) ? -1 : (textA > textB) ? 1 : 0; 不会编辑你的答案,期望我至少能记住 Linting 的事情 :) - MikeT
发现这段代码存在问题。请使用大小写字母的组合,例如:credit_card_no 和 City。虽然代码可以对列表进行排序,但是以“c”开头的单词并没有被分组在一起。 - Kedar
8
我们可以简化为 return textA.localeCompare(textB);。 - Taran

263
为了支持Unicode:
objArray.sort(function(a, b) {
   return a.DepartmentName.localeCompare(b.DepartmentName);
});

15
要使用不区分大小写的版本,请在第二行使用以下代码: return a.DepartmentName.toLowerCase().localeCompare(b.DepartmentName.toLowerCase()); - Ben Barreth
5
每天学点新东西 - localeCompare 很酷,且第一个参数在所有浏览器上都得到支持。不错! - obzenner
14
@BenBarreth 没有理由将字符串转换为小写。localeCompare 的整个目的是将排序逻辑和本地化怪癖的管理工作移交给系统。如果在当前语言环境中进行不区分大小写的排序是正常的(如英语),则会自动完成:"Z" > 'a' // false "Z".localeCompare('a') // 1如果您希望偏离语言环境的默认设置,可以通过 localesoptions 参数发送覆盖选项:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Parameters - Jon z
请记住,这不是空安全的,需要在运行此代码之前检查“DepartmentName”是否为实际字符串,否则排序将因空指针异常而失败。 - Kris Boyd

49

使用ES6缩短代码

objArray.sort((a, b) => a.DepartmentName.toLowerCase().localeCompare(b.DepartmentName.toLowerCase()))

21
objArray.sort((a, b) => a.DepartmentName.localeCompare(b.DepartmentName))

14
var DepartmentFactory = function(data) {
    this.id = data.Id;
    this.name = data.DepartmentName;
    this.active = data.Active;
}

// use `new DepartmentFactory` as given below. `new` is imporatant

var objArray = [];
objArray.push(new DepartmentFactory({Id: 1, DepartmentName: 'Marketing', Active: true}));
objArray.push(new DepartmentFactory({Id: 2, DepartmentName: 'Sales', Active: true}));
objArray.push(new DepartmentFactory({Id: 3, DepartmentName: 'Development', Active: true}));
objArray.push(new DepartmentFactory({Id: 4, DepartmentName: 'Accounting', Active: true}));

function sortOn(property){
    return function(a, b){
        if(a[property] < b[property]){
            return -1;
        }else if(a[property] > b[property]){
            return 1;
        }else{
            return 0;   
        }
    }
}

//objArray.sort(sortOn("id")); // because `this.id = data.Id;`
objArray.sort(sortOn("name")); // because `this.name = data.DepartmentName;`
console.log(objArray);

演示: http://jsfiddle.net/diode/hdgeH/


10
objArray.sort( (a, b) => a.id.localeCompare(b.id, 'en', {'sensitivity': 'base'}));

这将按字母顺序排序,并且不区分大小写。它也非常简洁易读 :D


这也是唯一提到 'sensitivity': 'base' 的答案,根据 MDN 的说法,这在您的应用程序中会产生很大的差异。 - phantomraa
请参考以下链接中的代码来使用localeCompare方法对数组进行排序:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#sort_an_array - bilelz

8
// Sorts an array of objects "in place". (Meaning that the original array will be modified and nothing gets returned.)
function sortOn (arr, prop) {
    arr.sort (
        function (a, b) {
            if (a[prop] < b[prop]){
                return -1;
            } else if (a[prop] > b[prop]){
                return 1;
            } else {
                return 0;   
            }
        }
    );
}

//Usage example:

var cars = [
        {make:"AMC",        model:"Pacer",  year:1978},
        {make:"Koenigsegg", model:"CCGT",   year:2011},
        {make:"Pagani",     model:"Zonda",  year:2006},
        ];

// ------- make -------
sortOn(cars, "make");
console.log(cars);

/* OUTPUT:
AMC         : Pacer : 1978
Koenigsegg  : CCGT  : 2011
Pagani      : Zonda : 2006
*/



// ------- model -------
sortOn(cars, "model");
console.log(cars);

/* OUTPUT:
Koenigsegg  : CCGT  : 2011
AMC         : Pacer : 1978
Pagani      : Zonda : 2006
*/



// ------- year -------
sortOn(cars, "year");
console.log(cars);

/* OUTPUT:
AMC         : Pacer : 1978
Pagani      : Zonda : 2006
Koenigsegg  : CCGT  : 2011
*/

6

因为这里所有的解决方案都是没有考虑 null/undefined 安全操作的,所以我会这样处理(你可以根据自己的需求处理 null):

ES5

objArray.sort(
  function(a, b) {
    var departmentNameA = a.DepartmentName ? a.DepartmentName : '';
    var departmentNameB = b.DepartmentName ? b.DepartmentName : '';

    return departmentNameA.localeCompare(departmentNameB);
  }
);

ES6+

objArray.sort(
 (a: DepartmentFactory, b: DepartmentFactory): number => {
   const departmentNameA = a.DepartmentName ? a.DepartmentName : '';
   const departmentNameB = b.DepartmentName ? b.DepartmentName : '';

   return departmentNameA.localeCompare(departmentNameB);
 }
);

我还删除了其他人使用的toLowerCase,因为localeCompare是不区分大小写的。并且我更喜欢在使用TypeScript或ES6+时对参数进行更明确的说明,以使未来的开发人员更加明确。


1
两种排序实际上都没有返回任何内容,因此没有进行排序。此外,您可以缩短三元运算符以使用空值合并运算符(??)。 - RogerSmith
@RogerSmith 谢谢您的评论!您是正确的,我错误地忘记返回 localeCompare 的结果。 ?? 运算符是在 ES2020 中引入的,所以在 2021 年,由于与原生 JS 的浏览器兼容性问题,我会犹豫使用任何新的东西。还有一个小提示,?? 是“空值合并运算符”,空合并运算符是 xxx?.yyy... 在名称上有微小的语义差异,但在实现中具有重要的影响。Nullish 的工作方式与 Falsey 一样奇怪,并且具有比三元运算符略微不同的优先级。我倾向于使用三元运算符以实现兼容性和明确的语法。 - Kris Boyd

5

DEMO

var DepartmentFactory = function(data) {
    this.id = data.Id;
    this.name = data.DepartmentName;
    this.active = data.Active;
}

var objArray = [];
objArray.push(new DepartmentFactory({Id: 1, DepartmentName: 'Marketing', Active: true}));
objArray.push(new DepartmentFactory({Id: 2, DepartmentName: 'Sales', Active: true}));
objArray.push(new DepartmentFactory({Id: 3, DepartmentName: 'Development', Active: true}));
objArray.push(new DepartmentFactory({Id: 4, DepartmentName: 'Accounting', Active: true}));

console.log(objArray.sort(function(a, b) { return a.name > b.name}));

2

像这样做

objArrayy.sort(function(a, b){
 var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase()
 if (nameA < nameB) //sort string ascending
  return -1
 if (nameA > nameB)
  return 1
 return 0 //default return value (no sorting)
});
console.log(objArray)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接