2 に答える
わかった。あなたが発見したように、あなたの問題は、デフォルトの JavaScript ソートが安定していることが保証されていないことです。具体的には、あなたの心の中では次のように機能すると思います。青さでソートし、緑さでソートすると、ソーターは配列内のエントリを上下に移動しますが、青さで並べ替えます。悲しいことに、宇宙はそれほど都合よく配置されているわけではありません。組み込みの JS ソートは、好きなようにソートできます。特に、配列の内容を大きなバケツに放り込んでから、以前の配置方法を完全に無視して、要求したとおりに並べ替えて取り出すことが許可されており、少なくとも一部のブラウザーは正確にそれを行っているようです。
あなたの特定の例では、これを回避する方法がいくつかあります。まず、3 つの別々の呼び出しで並べ替えを行うこともできますが、それらの呼び出しが安定して並べ替えを行うことを確認してください。これは、青さで並べ替えた後、緑度で安定して並べ替えることを意味し、緑度で並べ替えられた配列が得られ、その中の青さの順序で(つまり、まさに探しているものです)。私のソート可能ライブラリは、「シェーカー ソート」または「カクテル ソート」メソッド (http://en.wikipedia.org/wiki/Cocktail_sort) を実装することでこれを行います。基本的に、このスタイルの並べ替えでは、リストを何度も調べて項目を上下に移動します。(特に、それがしないものすべきことは、すべてのリスト項目をバケツに放り込んで、順番に引き戻すだけです。) ウィキペディアの記事に素敵な小さなグラフィックがあります。これは、「サブソート」がソートされたままであることを意味します。つまり、ソートが安定していて、必要なものが得られるということです。
ただし、この使用例では、3 つの異なる呼び出しで並べ替えを実行し、それらが安定していることを確認することなどについて心配する必要はありません。代わりに、すべての並べ替えを一度に行います。RGB カラー インジケーター (255、192、80) は、実際には奇妙な基数の大きな数であると考えることができます: 過度の数学を避けるために、基数 1000 であると想像してください (そのフレーズが意味をなさない場合は、無視してください。考えてみてください)。 CSS がカスケードで優先順位を計算する方法に少し似ています)。その数は、実際には 255,192,080 と考えることができます。行ごとにこの数値を計算し、この数値で並べ替えると、すべてうまくいき、並べ替えは 1 回だけで済みます。つまり、3 回並べ替えを行う代わりに、1 回行うことができますsorter.sort(function(a,b) { return (a.red*1000000 + a.green*1000 + a.blue) - (b.red*1000000 + b.green*1000 + b.blue) }
。すべてうまくいくでしょう。
技術的には、ソート関数が呼び出されるたびにその「ベース 1000 数」を計算する必要があるため、これは少し非効率的です。それが大きな問題である場合 (ベンチマークすることで解決できます)、シュワルツ変換を使用できます(流行語ばかりで申し訳ありません)。リスト内のすべて、リストを並べ替えてから、並べ替えられたリストを調べます。したがって、次のようなリストを作成し、[ [255192080, <table row 1>], [255255255, <table row 2>], [192000000, <table row 3>] ]
そのリストをソートします(次のような関数を使用してmylist.sort(function(a,b) { return a[0]-b[0]; })
)、次に、そのリストを調べて、各 s をテーブルに appendChild します。これにより、テーブル全体が順番に並べ替えられます。取得したテーブルにこの最後の段落はおそらく必要ありませんが、便利な場合があり、sorttable.js も使用するこのトリックについて知っておくと害はありません。
私は別の方法でこの問題に取り組みます。マークアップからデータを抽出してすべてのデータを再構築しようとしているようですが、これは危険な作業になる可能性があります。より簡単な方法は、プログラムが最初から理解できる形式でページにレンダリングするすべてのデータを表現し、最初にページの読み込み時にマークアップを再生成し、その後の並べ替えごとに単純に再生成することです。
例えば:
var colorsData = [
{
keyword: 'mediumspringgreen',
decimalrgb: {
r: 0,
g: 250,
b: 154
},
percentrgb: {
r: 0,
g: 98,
b: 60.4
},
hsl: {
h: 157,
s: 100,
l: 49
}
hex: '00FA9A',
shorthex: undefined
},
{
//next color...
}
];
そうすれば、この配列に対して好きな方法で並べ替えを実行でき、マークアップからデータを取り出して分割し、再割り当てする必要はありません。
しかし、実際には、ソート機能に夢中になっているようです。複数の並べ替えを次々に実行すると、意図しない結果が得られます。前の列が等しいことがわかった場合、次の「列」を比較する単一の並べ替え関数を実行する必要があります。RGB ソートは次のようになります。
var decimalRgbForwards = function(a,b) {
var a = a.decimalrgb,
b = b.decimalrgb;
if ( a.r === b.r ) {
if ( a.g === b.g ) {
return a.b - b.b;
} else {
return a.g - b.g;
}
} else {
return a.r - b.r;
}
};
したがって、r と g の値が一致する 2 つの色は、b の値が等しい場合に返されます。これはまさに探しているものです。
次に、並べ替えを適用できます。
colorsData.sort(decimalRgbForwards);
..そして最後に、その配列を繰り返し処理して、テーブル内のマークアップを再構築します。
お役に立てば幸いです、サー-