これらの回答はいずれも、並べ替えで複数のフィールドを使用するための汎用的な方法として理想的ではありません。上記のアプローチはすべて、配列を複数回ソートする必要がある(十分に大きいリストでは処理速度が大幅に低下する可能性がある)か、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 } ]
私がこの方法を好む理由は、任意の数のフィールドで高速ソートを可能にし、大量のガベージを生成したり、ソート内で文字列連結を実行したりせず、一部の列が逆ソートされるように簡単に使用できるためです。ソート。