这些答案都不是理想的通用方法,用于在排序中使用多个字段。上述所有方法效率不高,因为它们要么需要多次对数组进行排序(在足够大的列表中可能会使事情减慢很多),或者它们会产生大量的虚拟机清理所需的垃圾对象(并且最终会减慢该程序下降)。
这里的一个解决方案,快速,高效,容易地允许反向排序,并且可以与underscore
或lodash
,或直接用于与Array.sort
最重要的部分是compositeComparator
方法,该方法比较器的阵列函数并返回一个新的复合比较器函数。
/**
* Chains a comparator function to another comparator
* and returns the result of the first comparator, unless
* the first comparator returns 0, in which case the
* result of the second comparator is used.
*/
function makeChainedComparator(first, next) {
return function(a, b) {
var result = first(a, b);
if (result !== 0) return result;
return next(a, b);
}
}
/**
* Given an array of comparators, returns a new comparator with
* descending priority such that
* the next comparator will only be used if the precending on returned
* 0 (ie, found the two objects to be equal)
*
* Allows multiple sorts to be used simply. For example,
* sort by column a, then sort by column b, then sort by column c
*/
function compositeComparator(comparators) {
return comparators.reduceRight(function(memo, comparator) {
return makeChainedComparator(comparator, memo);
});
}
你还需要一个比较器函数来比较你想排序的字段。 naturalSort
函数将创建一个给定特定字段的比较器。编写一个反向排序的比较器也是微不足道的。
function naturalSort(field) {
return function(a, b) {
var c1 = a[field];
var c2 = b[field];
if (c1 > c2) return 1;
if (c1 < c2) return -1;
return 0;
}
}
(所有的代码到目前为止是可重复使用,并且可以保存在应用模块,例如)
接下来,你需要创建复合比较。对于我们的示例,它将如下所示:
var cmp = compositeComparator([naturalSort('roomNumber'), naturalSort('name')]);
这将按房间号排序,然后是名称。添加其他排序标准并不重要,不会影响排序的性能。
var patients = [
{name: 'John', roomNumber: 3, bedNumber: 1},
{name: 'Omar', roomNumber: 2, bedNumber: 1},
{name: 'Lisa', roomNumber: 2, bedNumber: 2},
{name: 'Chris', roomNumber: 1, bedNumber: 1},
];
// Sort using the composite
patients.sort(cmp);
console.log(patients);
返回以下
[ { name: 'Chris', roomNumber: 1, bedNumber: 1 },
{ name: 'Lisa', roomNumber: 2, bedNumber: 2 },
{ name: 'Omar', roomNumber: 2, bedNumber: 1 },
{ name: 'John', roomNumber: 3, bedNumber: 1 } ]
我喜欢这种方法是,它允许快速排序的字段任意数量,不会产生大量的垃圾或执行排序中字符串连接的原因并且可以轻松地使用,以便某些列反向排序,而订单列使用自然排序。
有一个[博客文章](http://blog.falafel.com/nifty-underscore-tricks-sorting-by-multiple-properties-with-underscore/)扩展了这一点,并包括有关排序升序和降序属性。 – 2014-10-07 15:13:51
+1:我认为这应该是被接受的答案:o) – Andrew 2014-10-21 04:05:32
正是我所期待的。谢谢! – 2015-11-07 15:14:30