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

4095
我有一个JavaScript对象的数组:
var objs = [ 
    { first_nom: 'Laszlo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

如何在JavaScript中按last_nom的值对它们进行排序?
我知道sort(a,b),但似乎只适用于字符串和数字。我需要在我的对象中添加toString()方法吗?

2
大小写敏感或不敏感排序? - Peter Mortensen
61个回答

10

为了避免混淆,您可能需要将它们转换为小写形式。

objs.sort(function (a, b) {

    var nameA = a.last_nom.toLowerCase(), nameB = b.last_nom.toLowerCase()

    if (nameA < nameB)
      return -1;
    if (nameA > nameB)
      return 1;
    return 0;  // No sorting
})

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

2
请考虑编辑您的帖子,添加更多关于代码的解释以及为什么它可以解决问题的说明。一个主要只包含代码(即使它是有效的)的答案通常不能帮助提问者理解他们的问题。 - Drenmi

9
您可以使用可重复使用的排序函数。
Array.prototype.order = function (prop, methods = {}) {
    if (prop?.constructor == Object) {
        methods = prop;
        prop = null;
    }
    const [orderType_a, orderType_b] = methods.reverse ? [1, -1] : [-1, 1];

    const $ = x => prop
        ? methods.insensitive
            ? String(x[prop]).toLowerCase()
            : x[prop]
        : methods.insensitive
            ? String(x).toLowerCase()
            : x;

    const fn = (a, b) => $(a) < $(b) ? orderType_a : $(b) < $(a) ? orderType_b : 0;
    return this.sort(fn);
};

它可以用来对数组和数组中的对象进行排序。

let items = [{ x: "Z" }, 3, "1", "0", 2, { x: "a" }, { x: 0 }];
items
    .order("x", { insensitive: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, '1', '0', 2, { x: 'Z' } ]
    .order({ reverse: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, 2, { x: 'Z' }, '1', '0' ]
    .sort(x => typeof x == "string" || typeof x == "number" ? -1 : 0)
    // [ '0', '1', 2, 3, { x: 0 }, { x: 'a' }, { x: 'Z' } ]

第一步(可选) > 对包含在数组中的对象进行排序。
第二步是方法 > { reverse: any, insensitive: any }


8
这是一个简单的问题。我不知道为什么人们有如此复杂的解决方案。
一个简单的排序函数(基于快速排序算法):
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');

6
在 JavaScript 中实现快速排序算法为何是一个简单的解决方案?快速排序算法本身简单,但实现并不简单。 - Andrew
这很简单,因为它不使用任何外部库,也不改变对象的原型。在我看来,代码的长度对代码的复杂性没有直接影响。 - Gil Epshtain
3
让我用不同的措辞来试试:重新发明轮子如何成为一个简单的解决方案? - Roberto14

8

根据您的示例,您需要按照两个字段(姓氏、名字)进行排序,而不是一个。您可以使用Alasql库在一行中完成此排序:

var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

可以在JSFiddle上尝试这个例子(点击此处)


7
简单回答:
objs.sort((a,b)=>a.last_nom.localeCompare(b.last_nom))

细节:

今天非常简单,您可以使用 localeCompare 比较字符串。正如 Mozilla Doc 中所说:

localeCompare() 方法返回一个数字,指示参考字符串在排序顺序中是在给定字符串之前,之后还是与其相同。

    //example1:
    console.log("aaa".localeCompare("aab")); //-1
    console.log("aaa".localeCompare("aaa")); //0
    console.log("aab".localeCompare("aaa")); //1


    //example2:
    const a = 'réservé'; // with accents, lowercase
    const b = 'RESERVE'; // no accents, uppercase

    console.log(a.localeCompare(b));
    // expected output: 1
    console.log(a.localeCompare(b, 'en', { sensitivity: 'base' }));
    // expected output: 0

更多详情请参见 Mozilla 文档localeCompare


7

方法1:

您可以使用Underscore.js。首先导入underscore

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');

方法二:使用比较函数。

function compare(first, second) {
     if (first.last_nom < second.last_nom)
         return -1;
     if (first.last_nom > second.last_nom)
       return 1;
    return 0;
 }

objs.sort(compare);

6
let propName = 'last_nom';

let sorted_obj = objs.sort((a,b) => {
    if(a[propName] > b[propName]) {
        return 1;
    }
    if (a[propName] < b[propName]) {
        return -1;
    }
    return 0;
}

//This works because the js built-in sort function allows us to define our
//own way of sorting, this funny looking function is simply telling `sort` how to
//determine what is larger. 
//We can use `if(a[propName] > b[propName])` because string comparison is already built into JS
//if you try console.log('a' > 'z' ? 'a' : 'z')
//the output will be 'z' as 'a' is not greater than 'z'
//The return values 0,-1,1 are how we tell JS what to sort on. We're sorting on the last_nom property of the object. 
//When sorting a list it comes down to comparing two items and how to determine which one of them is "larger". 
//We need a way to tell JS how to determine which one is larger. 
//The sort defining function will use the case that returns a 1 to mean that a > b
//and the case that returns -1 to mean that a < b


1
你能简要描述一下返回值1、-1、0吗? - stuckoverflow
1
这是我们告诉JS按什么排序的方式。我们正在按对象的last_nom属性进行排序。 在对列表进行排序时,它归结为比较两个项目以确定哪一个“更大”。我们需要一种方法来告诉JS如何确定哪一个更大。 定义排序函数将使用返回1表示a > b的情况,并且返回-1的情况是a < b的情况。 - DonCarleone
1
你能否将它添加到答案中(评论可能随时被删除)?但是请不要包含“编辑:”,“更新:”或类似的内容 - 答案应该看起来像是今天写的。 - Peter Mortensen
@stuckoverflow 请参阅Intl.Collator.prototype.compare() > 描述:"compare getter 函数返回一个数字,根据此 Intl.Collator 对象的排序顺序,指示 string1string2 相互比较的结果:如果 string1string2 之前,则返回负值;如果 string1string2 之后,则返回正值;如果它们被认为相等,则返回 0。" - Gerold Broser

5

使用 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"}
*/

5

对对象数组进行排序

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

// Property to sort by
var args = "last_nom";

// Function to sort the data by the given property
function sortByProperty(property) {
    return function (a, b) {
        var sortStatus = 0,
            aProp = a[property].toLowerCase(),
            bProp = b[property].toLowerCase();
        if (aProp < bProp) {
            sortStatus = -1;
        } else if (aProp > bProp) {
            sortStatus = 1;
        }
        return sortStatus;
    };
}

// Implementation
var sortedArray = booksArray.sort(sortByProperty(args));

console.log("sortedArray: " + JSON.stringify(sortedArray) );

控制台日志输出:

"sortedArray: 
[{"first_nom":"Pig","last_nom":"Bodine"},
{"first_nom":"Lazslo","last_nom":"Jamf"},
{"first_nom":"Pirate","last_nom":"Prentice"}]"

根据这个来源进行了修改:代码片段:如何按属性排序JSON对象数组


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