質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

2回答

792閲覧

jQuery の sort で、「指定キーいずれかについて」でソートできますか?

kuroean

総合スコア12

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2019/08/11 08:54

編集2019/08/11 12:38

###実現したいこと
下記arrayに「●_num」というキーがあります。(●の値はxyz以外にもいろいろです)

これに対してextKeysで指定したキーでソートしたいです。

###対象のコード

const array = [ {id: '1', x_num: '200', y_num: "", z_num: "" }, {id: '2', x_num: "", y_num: '100', z_num: "" }, {id: '3', x_num: "", y_num: "", z_num: '300' }, {id: '4', x_num: '100', y_num: '200', z_num: "" } ];

###試したこと
下記ではconst extKeys = [ 'x_num', 'y_num' ];と指定していますので、取得したいのは
[ '1', '2', '4', '3' ]の順のIDです。
[ '1', '4', '2', '3' ]の順のIDです。

まず最大の200を持つ1が最初にきて、あとは24が同じ100なのでそのまま入ります。そして空の3は最後です。

const extKeys = [ 'x_num', 'y_num' ]; array.sort( function( a, b ) { $.each( extKeys,function( index, val ){ if ( a[v] < b[v] ) return -1; if ( a[v] > b[v] ) return 1; return 0; }) }); console.log( array ); // 上の extKeys なら[ '1', '2', '4', '3' ]を取得したい

別の例として、もしconst extKeys = [ 'x_num' ];だけならば、[ '1', '4', '2', '3' ]がほしいです。

わかりにくい部分あるかもしれませんが、宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun68ykt

2019/08/11 10:23

こんにちは。ご質問で求められているソートの要件は、次の(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 の値が同じ要素については、順序を変えないようにする。
kuroean

2019/08/11 12:03 編集

こんにちは。宜しくお願い致します。 解釈の(2)についてだけ訂正させてください。「まずx_numを比較して、次にy_numの値で比較する」というような順序があるのではなく、 「extKeys をまぜて一気に」という感じを考えておりました。 つまりもし extKeys が [ 'x_num', 'y_num', 'z_num' ] のように3つあった場合、ほしい値は ["3","1","4","2"] になります。 「まずx_numを比較する」ならば最初に1が来ますが(200が最大だから)、「一気に比較する」ので最初に3が来る(300が最大だから)、ということです。 ご推察の手間をとらせてしまったこと、お詫びいたします。
guest

回答2

0

ベストアンサー

こんにちは

質問への追記・修正のほうから、以下のような要件確認の質問をさせて頂きました。

こんにちは。ご質問で求められているソートの要件は、次の(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に上げました。

投稿2019/08/11 10:44

編集2019/08/11 13:10
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kuroean

2019/08/11 11:35

jsFiddle 拝見いたしました。見事なコードをどうもありがとうございます。makeCompare がかなり難易度が高いですね。アロー関数❓から調べているレベルです。 特に [...array」の ... などは、一体なんだこれわという感じです。笑 冒頭の要件につきましては、「質問への追記・修正」の欄に(2)の訂正を記載させていただきました。もしよろしければまたお力添えいただけましたら幸いです。
jun68ykt

2019/08/11 12:31

コメントありがとうございます。 以下の3点(1)(2)(3) を返答します。なお(2)は、要件を確認する質問になっておりますので返信頂ければと思います。 (1) 回答に追記しました。この追記は、質問への追記・修正の依頼のほうから頂きました > 「extKeys をまぜて一気に」という感じ とのコメントを、コードに落とせる詳細に解釈したうえで、 makeCompare を修正したものです。 (2) まだご要望のものになっていない点のご確認 回答に追記したmakeCompareの修正版のコードでも、まだご要望のものになっていないということは認識しておりまして、それは、 extKeysが ["x_num","y_num"] のとき、追記したコードだと結果が ['1', '4', '2', '3' ] になりますが、ご要望の結果は、ご質問には > [ '1', '2', '4', '3' ] とあって、違っています。 ついては、こちらの理解不足で申し訳ありませんが、 ["x_num","y_num"] のとき、ご要望のソートでは {id: '2', x_num: "", y_num: '100', z_num: "" } のほうが {id: '4', x_num: '100', y_num: '200', z_num: "" } よりも前にくるのは、どのように各プロパティを比較した結果なのか、ご教示頂けますでしょうか? (3) コメントに返答します。 ・アロー関数について makeCompare は、 sort の引数として与える比較関数を返しています。アローを使わないで書くと以下のようになります。 function makeCompare(keys) { return function (obj1, obj2) { const key = keys.find(k => obj1[k] !== obj2[k]); return key ? obj2[key] - obj1[key] : 0; } } ・スプレッド構文について [...array] はスプレッド構文です。 参考: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax array.sort(・・・) と書いてしまうと、 array 自体の順序を変えてしまうので、[...array] で array のコピーを作ってそれをsortしています。
kuroean

2019/08/11 12:51

(1) 至らぬ表現について、丁寧で正確な解釈をありがとうございます。さすが、宣教師と人食い人種をプログラムできるレベルの方ですね…笑 以後要件の表現について気を付けるよう心がけます。 (2) これについてお詫びのしようがございません。質問を訂正致しました。 質問文 [ '1', '2', '4', '3' ] 訂正後 [ '1', '4', '2', '3' ] つまり、戴いたコードと解釈にまったく問題ございません。(おそらくその間違いにもお気づきでしょうに、まったくイヤミも感じさせない丁寧な物言いに大変恐縮しております。コードとは無関係ですが、そのお人柄に重ねて感謝申し上げます。) (3) ありがとうございます!今スクロールしながらさて(3)は何だろうと思ったら、まさかのお勉強タイムでした!笑 アロー関数はぼんやりつかめたものの、点々は検索してもわからなかったのでうれしいです。スプレッド構文、おぼえておきます。 至れり尽くせりのご回答に、ひどい状態で質問した自分が大変恥ずかしく思いました。夜分遅くに本当にありがとうございました。<(_ _)>
jun68ykt

2019/08/11 13:23

どういたしまして。追記したコードで、ご質問の要件が満たされていたとのことで、よかったです ???? そして、 > 宣教師と人食い人種を・・・ との件、拙稿をご覧頂きましてありがとうございました。٩(ˊᗜˋ*)و
guest

0

array.sort( function( a, b ) { $.each( extKeys,function( index, val ){ if ( a[v] < b[v] ) return -1; if ( a[v] > b[v] ) return 1; return 0; }) });

あなたの書いたプログラムを動かしてみたところ
Uncaught ReferenceError: v is not defined
というエラーが出ました。

自分でデバッグする努力を放棄してプログラムの作成を回答者に丸投げしていませんか?

vをvalに直しましょう。

valに直しても動きませんのでデバッグのため$.eachの返却値を調べる必要があります。

array.sort( function( a, b ) { var ret=$.each( extKeys,function( index, val ){ if ( a[val] < b[val] ) return -1; if ( a[val] > b[val] ) return 1; return 0; }); console.log(ret); });

$.eachの返却値をconsole.logで表示させてみたところextKeysを表示しました。
-1や1を返すように直さなければなりません。

array.sort( function( a, b ) { for(var i=0; i<extKeys.length; i++) { var val = extKeys[i]; if ( a[val] < b[val] ) return -1; if ( a[val] > b[val] ) return 1; } return 0; });

$.eachは何をしているかとてもわかりにくいので使用するときは要注意です。
普通にfor文で書くのがいいでしょう。

投稿2019/08/11 09:46

querykuma

総合スコア777

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kuroean

2019/08/11 11:25

質問時に「v」じゃわかりにくいから「val」にしよう。と気を遣って変えたのだという風にも取れると思うので、どうか勘繰らずにお手柔らかにお願いします。 なるほど、forの方がわかりやすいのですね。いまいち違いがわかっていないので調べておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問