Không có câu trả lời nào là lý tưởng để sử dụng nhiều trường trong một sắp xếp. Tất cả các phương pháp trên đều không hiệu quả vì chúng yêu cầu sắp xếp mảng nhiều lần (trong đó, trên một danh sách đủ lớn có thể làm chậm nhiều thứ) hoặc chúng tạo ra một lượng lớn các đối tượng rác mà VM cần phải dọn dẹp (và cuối cùng làm chậm chương trình xuống).
Dưới đây là một giải pháp mà là nhanh chóng, hiệu quả, dễ dàng cho phép đảo ngược phân loại, và có thể được sử dụng với underscore
hoặc lodash
, hoặc trực tiếp với Array.sort
Phần quan trọng nhất là compositeComparator
phương pháp, trong đó có một loạt các so sánh và trả về một hàm so sánh tổng hợp mới.
/**
* 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);
});
}
Bạn cũng sẽ cần một hàm so sánh để so sánh các trường bạn muốn sắp xếp. Hàm naturalSort
sẽ tạo một trình so sánh cho một trường cụ thể. Viết một so sánh để phân loại ngược là tầm thường quá.
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;
}
}
(Tất cả các mã cho đến nay là tái sử dụng và có thể được giữ trong mô-đun tiện ích, ví dụ)
Tiếp theo, bạn cần phải tạo ra các so sánh composite. Ví dụ của chúng tôi, nó sẽ giống như sau:
var cmp = compositeComparator([naturalSort('roomNumber'), naturalSort('name')]);
Điều này sẽ sắp xếp theo số phòng, theo sau là tên. Thêm tiêu chí sắp xếp bổ sung là tầm thường và không ảnh hưởng đến hiệu suất sắp xếp.
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);
Trả về sau
[ { name: 'Chris', roomNumber: 1, bedNumber: 1 },
{ name: 'Lisa', roomNumber: 2, bedNumber: 2 },
{ name: 'Omar', roomNumber: 2, bedNumber: 1 },
{ name: 'John', roomNumber: 3, bedNumber: 1 } ]
Lý do tôi thích phương pháp này là nó cho phép nhanh chóng sắp xếp trên một số tùy ý các lĩnh vực, không tạo ra rất nhiều rác hoặc thực hiện chuỗi nối bên trong loại và có thể dễ dàng được sử dụng để một số cột được sắp xếp ngược lại trong khi các cột thứ tự sử dụng sắp xếp tự nhiên.
Có một [bài đăng blog] (http://blog.falafel.com/nifty-underscore-tricks-sorting-by-multiple-properties-with-underscore/) mở rộng về điều này và bao gồm thông tin tốt về sắp xếp tăng dần và thuộc tính giảm dần. –
+1: Tôi nghĩ rằng đây phải là câu trả lời được chấp nhận: o) – Andrew
Chỉ là những gì tôi đang tìm kiếm. Cảm ơn bạn! –