假设我有一个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
函数获取这些新索引似乎不可能。但我很高兴被证明是错的。
编辑:我试图这样做的方式效率太低而无法发挥作用。请参阅下面的答案,了解使用比较函数的解决方案。
答案 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];
});