在JavaScript中按照另一个的内容对数组进行排序

时间:2015-04-17 16:05:51

标签: javascript arrays sorting dictionary

假设我有一个Person对象数组:

var people = [{name: "Joe Schmo", age: 36}, {name: "JANE DOE", age: 40}];

我有一个函数可以对字符串数组进行不区分大小写的排序:

function caseInsensitiveSort(arr) { ... }

是否有任何简单的方法将我现有的排序函数与Array.prototype.map结合起来,只使用people键对name数组进行排序?

即。它会产生

var people = [{name: "JANE DOE", age: 40}, {name: "Joe Schmo", age: 36}];

在这种特殊情况下,手工完成并不难,

people.sort(function (a, b) {
    return a.name.localeCompare(b.name);
});

但我想不出一种方法可以让我使用预先存在的排序功能。在排序函数更加自定义的情况下,这将是有用的。

编辑:我认为这里的核心问题是,为了做到这一点,您需要能够找出在对代理数组进行排序时原始索引映射到的内容。在一般情况下,使用JS的本机sort函数获取这些新索引似乎不可能。但我很高兴被证明是错的。

编辑:我试图这样做的方式效率太低而无法发挥作用。请参阅下面的答案,了解使用比较函数的解决方案。

2 个答案:

答案 0 :(得分:4)

您可以使用现有函数获取已排序的名称数组,然后通过比较已排序名称数组中的索引对people数组进行排序。

var names = caseInsensitiveSort(people.map(function(person) { 
    return person.name;
}));

people.sort(function (a, b) {
    return names.indexOf(a.name) - names.indexOf(b.name);
});

但是效率不高,你应该尝试将caseInsensitiveSort函数的比较逻辑抽象为caseInsensitiveCompare函数。

然后你的例子将成为:

people.sort(function (a, b) {
    return caseInsensitiveCompare(a.name, b.name);
});

答案 1 :(得分:1)

根据caseInsensitiveSort()功能的工作原理,您可以使用.toString()方法执行此操作:

var toSort = people.map(function (person) {
    return {
        person: person,
        toString: function () {
            return person.name;
        }
    };
});

caseInsensitiveSort(toSort);

people = toSort.map(function (item) { return item.person; });

如果这不是一个选项,那么更简洁但仍然有效的方法是对名称进行排序,将它们映射到它们的索引,然后根据它进行排序:

var names = people.map(function (person) { return person.name; });

caseInsensitiveSort(names);

var nameMap = {};
names.forEach(function (name, i) { 
    nameMap[name] = i;
});

people.sort(function (a, b) {
    return nameMap[a.name] - nameMap[b.name];
});