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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

Q&A

3回答

1266閲覧

javascriptの数値のソートで文字列を最終位置にしたい

Izumo1101

総合スコア49

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

0グッド

0クリップ

投稿2020/09/27 23:40

nodeサーバーにてjsonファイルの並べ替えを行った後にクライアントにデータを送信しています。以下は2つともサーバー側の記述です。

javascript

1 function object_array_sort(data,key,order,fn){ 2 var num_a = -1; 3 var num_b = 1; 4 5 if(order === 'asc'){ 6 num_a = 1; 7 num_b = -1; 8 } 9 data = data.sort(function(a, b){ 10 var x = parseFloat(a[key]); 11 var y = parseFloat(b[key]); 12 if (x > y) return num_a; 13 if (x < y) return num_b; 14 return 0; 15 }); 16 fn(data); // ソート後の配列を返す 17 }

javascript

1//記録でソート 2 var matubi = name.slice( -1 ) ; 3 if(matubi == "ア"){ 4 var ii= 'asc'; 5 }else{ 6 var ii= 'desc'; 7 } 8 if(name.slice( -3 ) == "アイウ"){ 9 var iii= 'r9'; 10 }else{ 11 var iii= 'r0'; 12 } 13 14 15 object_array_sort(items, iii, ii, function(new_data){ 16 17 for (i in new_data) { 18 item = new_data[i]; 19 ID = item.id; 20        //↓以下抽出等の記述が続きクライアントにデータを送信

要するに条件を付けて並べ替えを行い、それによってデータをクライアントに送っているわけですが、json項目r0には小数を含む数値が入っています。要するに記録です。その中には「失格」「失格13.05」(参考記録的な)なども含まれており、これらを順番付けする際に困っています。

結果:
1位 11.5
2位 失格
3位 12.55


7位 失格13.05

等となってしまうのです。
1つ目の関数object_array_sortにて、parseFloat()で数値として読み取っていたつもりなのですが何がおかしいのでしょうか。
正しくは
希望:
1位 11.5
2位 12.55




40位 失格13.05
41位 失格
のような形で(40と41位は順序は特にこだわらない)並べ替えをしたいと思っています。

どなたかご教示ください。

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

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

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

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

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

Zuishin

2020/09/27 23:52

a[key] に「失格」と含まれていたら parseFloat() の代わりに Number.MAX_VALUE にすればいいんじゃないでしょうか。
guest

回答3

0

こんにちは

比較対象のどちらか(あるいは両方)のparseFloatが失敗して、NaNが返されてきた場合の条件分岐や対応を、sortに与える比較関数の中に入れてしまうと、やや煩雑になってしまいます。このようなときに自分がよくやる手は、sort の前に map を挟んで、配列要素のオブジェクトに 、ソートキーになる別のプロパティを追加することです。追加プロパティの値は、NaNのような(全順序関係を崩す)値をとらないように配慮された数値とすることで、sortに与える比較関数を簡単に書けるようにします。

以下はそのサンプルです。

まず、有効なスコアの最大値MAX_SCOREと、失格を表すスコアの定数DISQUALIFIED_SCOREを作っておきます。ここでは有効なスコアの最大値を仮に、100.0 とし、それに1.0を加えた値が失格を表すスコアとしました。

javascript

1// 有効なスコアの最大値と、失格を表すスコア 2const MAX_SCORE = 100.0; 3const DISQUALIFIED_SCORE = MAX_SCORE + 1.0;

失格を表すスコアの値は、昇順ソートしたときに、失格が後にくるようにするためには、有効なスコアの最大値よりも大きい値にする必要があります。

上記で決めた DISQUALIFIED_SCORE を使って、冒頭に書いた mapを挟むコードの一案は以下です。

javascript

1data = data.map(a => ( 2 { ...a, score: a[key] >= 0 ? +a[key] : DISQUALIFIED_SCORE } 3 )) 4 .sort((a, b) => (ii === 'asc' ? 1 : -1) * (a.score - b.score));

上記では、ソート用に追加するキーを scoreとしています。また、有効なスコアを0以上の数値としています。以下で動作確認できます。

以上、参考になれば幸いです。

追記

もうひとつ、別の方法を挙げておきます。与えられたdata全体をソートするのではなく、失格ではないデータ(= ソート対象プロパティを数値に変換したときにNaNにならないオブジェクト) だけを集めた配列を作り、ソートはこの配列に対して行って、ソート後に失格のオブジェクトのみを集めた配列と結合するという考え方です。

以下はそのコード例です。(有効なスコアは0以上の数値であることを前提にしています。)

javascript

1// 有効なスコアを持つオブジェクトのみの配列を作り、昇順にソートする。 2const qualifiedData = data.filter(a => a[key] >= 0).sort((a,b) => a[key] - b[key]); 3 4// 失格のオブジェクトのみを持つ配列を作る 5const disqualifiedData = data.filter(a => Number.isNaN(+a[key])); 6 7// data を、有効スコアの配列と失格スコアの配列を結合した配列に置き換える。 8data = [...qualifiedData, ...disqualifiedData]; 9 10// 降順指定であれば、全体の順序を逆にする。 11if (ii == 'desc') { 12 data.reverse(); 13}

投稿2020/09/28 03:12

編集2020/09/28 09:25
jun68ykt

総合スコア9058

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

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

Izumo1101

2020/09/28 12:56

皆さまの回答に感謝です。 工夫して失格や棄権をはじくことは私でもできますが、文言の違いや、そもそも数値以外をはじく根本的なアイディアをいただけたのでBAとさせていただきます。
jun68ykt

2020/09/29 14:15

どういたしまして。参考になれば幸いです。
guest

0

javascript

1const order="desc" 2const flg=(typeof order=="undefined"?"":order) === 'desc'?-1:1; 3const data=["失格","12.55","11.5","3.14"]; 4data.sort((x,y)=>(isNaN(x)||!isNaN(y))?flg:(x-y)); 5console.log(data); 6

投稿2020/09/28 00:33

yambejp

総合スコア114581

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

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

yambejp

2020/09/28 00:35

文字列と数値を同列でソートしてはまずいですね 上記文字列同士のソートも必要ならもうちょい工夫が必要
guest

0

javasucipt

1 var x = ('0000000000' + a[key]).substr(-10); // 前ゼロ10桁 2 var y = ('0000000000' + b[key]).substr(-10); // 前ゼロ10桁

※ちゃんと文字列も対応していますよ(強引ですが)

投稿2020/09/28 00:13

編集2020/09/28 04:50
kuma_kuma_

総合スコア2506

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問