Жоден із цих відповідей не є ідеальним як метод загального призначення для використання декількох полів у своєму роді. Усі вищезазначені підходи неефективні, оскільки вони або вимагають сортування масиву декілька разів (що за достатньо великим списком може значно уповільнити роботу), або вони генерують величезну кількість об'єктів для сміття, які VM знадобиться очистити (і врешті-решт уповільнити програма вниз).
Ось рішення, яке швидко, ефективно, легко дозволяє реверсувати сортування, і його можна використовувати з 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 } ]
Причиною, що я віддаю перевагу цьому методу, є те, що він дозволяє швидко сортувати за довільною кількістю полів, не генерує багато сміття або виконувати конкатенацію рядків всередині сортування, і його можна легко використовувати, щоб деякі стовпці було відтворено в зворотному порядку, а стовпці порядку використовують природне сортувати.