50

javascriptのソート関数をから切り替えることによって

myArray.sort(function (a, b) {
  return a.name.localeCompare(b.name);
});

myArray.sort(function (a, b) {
  return (a.name < b.name ? -1 : (a.name > b.name ? 1 : 0));
});

Chromeで最大1700要素の配列を並べ替える時間を1993ミリ秒から5ミリ秒に短縮することができました。ほぼ400倍のスピードアップ。残念ながら、これは英語以外の文字列を正しくソートすることを犠牲にして行われます。

明らかに、並べ替えを実行しようとすると、UIを2秒間ブロックすることはできません。ひどく遅いlocaleCompareを回避しながら、ローカライズされた文字列のサポートを維持するためにできることはありますか?

4

5 に答える 5

44

コレーターオブジェクトを事前に宣言し、そのcompareメソッドを使用することで、パフォーマンスを大幅に向上させることができます。例えば:

const collator = new Intl.Collator('en', { numeric: true, sensitivity: 'base' });
arrayOfObjects.sort((a, b) => {
  return collator.compare(a.name, b.name);
});

注:要素がフロートの場合、これは正常に機能しません。ここで説明を参照してください:Intl.Collat​​orと数値オプションを使用した自然ソートは10進数で正しくソートされません

3つの方法を比較するベンチマークスクリプトは次のとおりです。

const arr = [];
for (let i = 0; i < 2000; i++) {
  arr.push(`test-${Math.random()}`);
}

const arr1 = arr.slice();
const arr2 = arr.slice();
const arr3 = arr.slice();

console.time('#1 - localeCompare');
arr1.sort((a, b) => a.localeCompare(
  b,
  undefined, {
    numeric: true,
    sensitivity: 'base'
  }
));
console.timeEnd('#1 - localeCompare');

console.time('#2 - collator');
const collator = new Intl.Collator('en', {
  numeric: true,
  sensitivity: 'base'
});
arr2.sort((a, b) => collator.compare(a, b));
console.timeEnd('#2 - collator');

console.time('#3 - non-locale');
arr3.sort((a, b) => (a < b ? -1 : (a > b ? 1 : 0)));
console.timeEnd('#3 - non-locale');

于 2018-09-17T14:22:53.113 に答える
13

/ mostly /ラテン文字を処理するときに私が見つけた効果的なアプローチは、両方の文字列が特定の正規表現に一致する場合は常に演算子を使用することです。例えば:/^[\w-.\s,]*$/

両方の文字列が式に一致する場合ははるかに高速であり、最悪の場合、localeCompareを盲目的に呼び出すよりもわずかに遅いようです。

ここでの例:http://jsperf.com/operator-vs-localecompage/11

更新:現在、Intl.Collat​​orが全体的なパフォーマンスに最適なオプションのようです:https ://jsperf.com/operator-vs-localecompage/22

于 2014-09-10T21:35:06.587 に答える
6

並べ替えているデータを見ずに最速の並べ替えを知ることは困難です。しかし、jsperfには、ソートのタイプ間のパフォーマンスの違いを示す多くの優れたテストがあります。http: //jsperf.com/javascript-sort/45 http://jsperf.com/sort-algorithms/31

ただし、これらはいずれもローカライズされた文字列を考慮しておらず、ローカライズされた文字列を並べ替える簡単な方法はないと思います。localeCompareがおそらくこれに最適なソリューションです。

mozillaのリファレンスを見ると、「大きな配列の並べ替えなど、多数の文字列を比較する場合は、Intl.Collat​​orオブジェクトを作成し、そのcompareプロパティによって提供される関数を使用することをお勧めします。」 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

しかし、Intl.Collat​​orリファレンスにアクセスすると、firefox /safarihttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collat​​orがサポートされていないことがわかり ます。

localCompareのいくつかのオプションを使用して、パフォーマンスを高速化してみてください。しかし、感度レベルを変更する簡単なテストを行ったところ、パフォーマンスは向上しないようです。

list.sort(function(a, b) {
  return a.localeCompare(b, {sensitivity:'base'});
});

http://jsperf.com/sort-locale-strings

于 2013-10-24T21:38:10.457 に答える
2

2つのステップで並べ替えてみてください。

  1. オペレーターの場合:あなたが言ったように、それは400倍速くなります
  2. 次に、localCompare():を使用すると、配列がほとんどソートされているため、比較が少なくなります。

localCompare()注:ほとんどの場合、英語以外の文字列を少なくとも1つ使用して呼び出されると思います。したがって、localCompare()2つの英語の文字列を使用した呼び出しの数を大幅に減らす必要があります。

コードは次のとおりです。

myArray.sort(function(a, b) {
  return (a.name < b.name ? -1 : (a.name > b.name ? 1 : 0));
});

myArray.sort(function(a, b) {
  return a.name.localeCompare(b.name);
});

このソリューションには、短くて使いやすいという利点があります。配列に主に英語の文字列が含まれていると効率的です。英語以外の文字列が多いほど、最初の並べ替えの有用性は低くなります。ただし、スクリプトを追加するのは簡単なので、このアプローチが価値があるかどうかを確認するのも簡単です。

さて、私があなたなら、多くの比較を行う場合Intl.Collatorよりもはるかに高速であると言われているので、私もを使用します。localCompare()

于 2015-05-24T11:57:13.617 に答える
-3

あなたがまだこの問題の解決策を探しているのかわかりません

// Defaulted to ascending
// 1 asc | -1 desc
var direction = 1; 
myArray.sort(function (a, b) {
  return a.name.localeCompare(b.name) === 1 ? direction : -1 * direction;
});

私は=== 1あなたのコードにチェックを追加しました、そしてこの改善されたパフォーマンス400xは両方が同等のパフォーマンス番号を持っていることを意味します。

localeCompare arrサイズを使用したパフォーマンス番号:3200 10回の繰り返しにかかった平均時間:60ミリ秒

>アプローチのパフォーマンス番号。平均時間は55ミリ秒かかりました

于 2014-08-26T05:34:24.967 に答える