こんにちは
質問への追記・修正のほうから、以下のような要件確認の質問をさせて頂きました。
こんにちは。ご質問で求められているソートの要件は、次の(1) (2) (3) を満たすもの、という解釈でよいでしょうか?
(1) x_num, y_num のいずれについても、キーの値の降順(値が大きいものが先)になるようにソートする。
(2) extKeys が [ 'x_num', 'y_num' ] のときは、x_num をソートの第1キーとし、 y_numを第2キーとする。つまり、まず x_num の値で比較して、x_numの値が同じならば、y_numの値で比較する。
(3) extKeys が [ 'x_num' ] のときは、 x_num の値の降順でソートし、 x_num の値が同じ要素については、順序を変えないようにする。
以下の回答は、上記の(1)(2)(3)が、ご質問の要件として齟齬がないことを前提としたものですので、要件の解釈が間違っていましたら、コメントからご指摘ください。
ソートキーが [ 'x_num', 'y_num' ]
だったり[ 'x_num' ]
だったりと変わり得る状況で、上記の(1)(2)(3) を満たすようなソートを実行するコードは、たとえば以下のようになるかと思います。(※了解事項とは思いますが、空文字列は 0
として扱われます。)
まず、ソートキーの配列を受け取って比較関数を返す、以下のような高階関数を作ります。
javascript
1const makeCompare = (keys) => (
2 (obj1, obj2) => {
3 const key = keys.find(k => obj1[k] !== obj2[k]);
4 return key ? obj2[key] - obj1[key] : 0;
5 }
6);
上記を使って、与えられた array
の順番は変えずに、ソートされた id の配列を得るには以下のようにします。
javascript
1const extKeys1 = [ 'x_num', 'y_num' ];
2const comp1 = makeCompare(extKeys1);
3const result1 = [...array].sort(comp1).map(e => e.id);
javascript
1const extKeys2 = [ 'x_num' ];
2const comp2 = makeCompare(extKeys2);
3const result2 = [...array].sort(comp2).map(e => e.id);
以下は、上記を動作確認するために、 jsFiddle に上げたものです。
冒頭に書いた、ご質問の要件の解釈 (1),(2),(3) が間違っていましたら、コメントからご指摘頂ければと思います。
以上、参考になれば幸いです。
追記
質問への追記・修正の依頼のほうに
「extKeys をまぜて一気に」という感じ
とのご返答がありましたので、これを、コードに落とせるレベルの詳細としては、以下と解釈しました。(以下の(4) だけでソート要件は把握できるので、先の (1)(2)(3) の3つに変わるものです。)
(4) array の2つの要素 obj1 , obj2 について、 以下のように比較する。
obj1
のプロパティのうち、配列 extKeys
に含まれるものの最大値を max1
とする。
obj2
のプロパティのうち、配列 extKeys
に含まれるものの最大値を max2
とする。
- 上記の max1 と max2 を比較して、ソート後の obj1 と obj2 の順序を以下とする。
・ max1 > max2 ならば、 obj1 は obj2 よりも前
・ max1 = max2 ならば、 obj1 と obj2 の前後は変更されない
・ max1 < max2 ならば、 obj1 は obj2 よりも後
上記であるとすると、先の回答に書いた makeCompare
を以下のように修正します。
javascript
1const makeCompare = (keys) => (
2 (obj1, obj2) => {
3 const max1 = Math.max(...keys.map(k => +obj1[k]));
4 const max2 = Math.max(...keys.map(k => +obj2[k]));
5 return max2 - max1;
6 }
7);
上記のコードも動作確認用に以下のjsFiddleに上げました。