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

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

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

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

jQuery

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

Q&A

解決済

4回答

363閲覧

forEach文を使い配列の中身を入れ替えるシステムが思った挙動にならない

k0908

総合スコア102

JavaScript

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

jQuery

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

0グッド

0クリップ

投稿2018/05/24 01:57

forEach文を使い配列の中身を入れ替えるシステムが思った挙動にならない。

var young ="12"; var old ="59";

という2つの変数があり、このyoung変数~old変数までの間で
a2で該当する配列にソートをかけて、そのa2が含まれる辞書とその親の辞書のkeyを含む辞書を返し
data辞書の中身を入れ替えたい。

data={'A':[{'a1':10,'a2':'9'},{'a1':10,'a2':'79'}],'B':[{'a1':40,'a2':'99'},{'a1':30,'a2':'15'},{'a1':30,'a2':'80'},'C':[{'a1':'30','a2':'90']} Object.keys(data).forEach(function(x){ var y=data[x].filter(function(x){ return x["a2"]>=young && x["a2"]<=old; }).sort(function(x,y){ return x["a2"]==y["a2"]?0:(x[["a2"]<y["a2"]?1:-1); }); if(y.length>0) data[x]=y; });

とコードを書いたところ、
Cのキーの判定の時、

return x["a2"]>=young && x["a2"]<=old;

でfalseになり、yが空になり結果data配列も空になってしまう。
該当する辞書の要素をdata配列に入れるにはどうしたらいいか?

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

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

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

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

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

guest

回答4

0

まず、説明されている現象が発生しないコードを提示するのはやめてください

data={'A':[{'a1':10,'a2':'9'},{'a1':10,'a2':'79'}],'B':[{'a1':40,'a2':'99'},{'a1':30,'a2':'15'},{'a1':30,'a2':'80'},'C':[{'a1':'30','a2':'90']}

↑この時点ですでに実行時エラーが発生します。なぜか?
括弧の対応がくるっているからです

(ちなみに同じ指摘を同一投稿者の別の質問に対する回答でもやった記憶があります。)

エラーを起こさない、正しく括弧の対応ができた記述はこうなるはずです。

data={ 'A':[ {'a1':10,'a2':'9'}, {'a1':10,'a2':'79'} ], 'B':[ {'a1':40,'a2':'99'}, {'a1':30,'a2':'15'}, {'a1':30,'a2':'80'} ], 'C':[ {'a1':'30','a2':'90'} ] };

yが空になり結果data配列も空になってしまう

ありえません
空になるのはyだけのはずです。
forEachは各要素を順次処理するだけで、要素の削除は行いません。
filterは各要素の絞り込みを行って、新しい配列を作ります。

let func1 = function(){ const young ="12"; const old ="59"; let data={ 'A':[{'a1':10,'a2':'9'},{'a1':10,'a2':'79'}], 'B':[{'a1':40,'a2':'99'},{'a1':30,'a2':'15'},{'a1':30,'a2':'80'}], 'C':[{'a1':'30','a2':'90'}] }; // 提示されたコードではyを参照できないため、より広いscopeで宣言 let y = []; Object.keys(data).forEach(function(x){ y=data[x].filter(function(x){ return x["a2"]>=young && x["a2"]<=old; }).sort(function(x,y){ return x["a2"]==y["a2"]?0:(x["a2"]<y["a2"]?1:-1); }); if(y.length>0) data[x]=y; }); console.log(data); // 出力結果:元のdataオブジェクト console.log(y); // 出力結果:空の配列 };

該当する辞書の要素をdata配列に入れるには

↑別の変数を準備して、そこに入れればよいのでは?

let func1 = function(){ const young ="12"; const old ="59"; let data={ 'A':[{'a1':10,'a2':'9'},{'a1':10,'a2':'79'}], 'B':[{'a1':40,'a2':'99'},{'a1':30,'a2':'15'},{'a1':30,'a2':'80'}], 'C':[{'a1':'30','a2':'90'}] }; // 出力用の別変数。配列ってかオブジェクトにした。 let data2 = {}; Object.keys(data).forEach(function(x){ let y=data[x].filter(function(x){ return x["a2"]>=young && x["a2"]<=old; }).sort(function(x,y){ return x["a2"]==y["a2"]?0:(x["a2"]<y["a2"]?1:-1); }); if(y.length>0) data2[x]=y; // 出力用の別変数に詰め込みなおす }); console.log(data2); // [object Object]:{ B: Array[ { a1:30, a2 : "15" } ] } };

投稿2018/05/24 03:06

tkturbo

総合スコア5572

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

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

0

やりたいことは

  • オブジェクト A, B, C の配列の a2 プロパティを 12 <= a2 <= 59、で絞り込む
  • オブジェクト A, B, C の配列の a2 の大きい順で並び変える

で間違いないですか。
Object.entries, Object.fromEntries(*), Array.map を使うともっと簡潔に書くことが出来ます。
どうでもいいですが、イテレーターを反復するメソッド中でイテレーターを書き換える処理は危険に感じました。

js

1const data = { 2 A: [{ a1: 10, a2: 9 }, { a1: 10, a2: 79 }], 3 B: [{ a1: 40, a2: 99 }, { a1: 30, a2: 15 }, { a1: 30, a2: 80 }], 4 C: [{ a1: 30, a2: 90 }], 5}; 6 7const ageFilter = v => (v.a2 >= 12 && v.a2 <= 59); 8const sort = (a, b) => (b.a2 - a.a2); 9 10const result = Object.fromEntries(Object.entries(data).map(([key, value]) => { 11 const sortedData = value.sort(sort); 12 const filteredData = sortedData.filter(ageFilter); 13 if (filteredData.length) { 14 return [[key]: filteredData]; 15 } 16 return [[key]: value]; 17})); 18 19console.log(result);
  • Object.fromEntries は stage0 の実験段階中

https://tc39.github.io/proposal-object-from-entries/

投稿2018/05/24 03:01

og24715

総合スコア832

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

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

0

どうしたらいいか、に対する回答は、要件に添った動作でありどうしようもない、です。


dataのjsonのフォーマットが正しくない点を、要素の追加削除ではなく、カッコの修正だけで直して考えます。

Cのキーの判定の時、

とのことですが、cに含まれる唯一の要素のa2は90であり、young 12とold 59の範囲に入っていないため、falseになるのは、

このyoung変数~old変数までの間で

という定義された要件通りの動きかと思います。

また、if(y.length>0) data[x]=y;となっているため

yが空になり結果data配列も空になってしまう。

という挙動にはならないはずです(yが空の場合はdataへの上書きが起きないように仕掛けてあります)

ちなみに文法エラーを直してchromeのコンソールで確認する限り、要件に添った動作をしているように見えます。
(ただ、dataはやりたいことに対してマッチする条件が少ないので、テストケースとして非妥当に思えます。例えばこのデータではソートが意図した通り動いているかを判定することはできないと思います)

参考までに、ソートは文字列のソートになるので"9"と"79"だと"9"->"79","19"と"79"だと"79"->"19"という降順ソートになっているのが想定した動作なのか(ソートするとは書いていてもソートの要件は明示されていません)もあわせてご確認いただいたほうがいいかもしれません

投稿2018/05/24 02:48

papinianus

総合スコア12705

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

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

0

ベストアンサー

まずタイプミスが散見されます。質問がブレるので注意して下さい
比較をする際に、桁数が違う文字列を単純に比較すると頭から順に比較していきますので
自然数順になりません。数値として比較したいならparseIntをかませるなどの処理が必要です
またdataから抽出したデータをdataで受けるのはちょっとおかしいですね

javascript

1var data={ 2 'A':[ 3 {'a1':10,'a2':'9'}, 4 {'a1':10,'a2':'79'}, 5 ], 6 'B':[ 7 {'a1':40,'a2':'99'}, 8 {'a1':30,'a2':'15'}, 9 {'a1':30,'a2':'80'}, 10 ], 11 'C':[ 12 {'a1':'30','a2':'90'}, 13 ] 14 }; 15var young ="12"; 16var old ="59"; 17var new_data={}; 18Object.keys(data).forEach(function(x){ 19 var y=data[x].filter(function(x){ 20 return parseInt(x["a2"])>=parseInt(young) && parseInt(x["a2"])<=parseInt(old); 21 }).sort(function(x,y){ 22 return x["a2"]==y["a2"]?0:(parseInt(x["a2"])<parseInt(y["a2"])?1:-1); 23 }); 24 if(y.length>0) Object.defineProperty(new_data, x, {value:y}); /*修正*/ 25}); 26data=new_data; 27console.log(data); 28

一部修正しました

投稿2018/05/24 02:32

編集2018/05/24 03:08
yambejp

総合スコア114779

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

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

k0908

2018/05/24 02:39

ありがとうございます。dataから抽出したデータをdataで受けるのはおかしいと書かれた理由を教えてもらえますか?僕はdataの中身を入れ替えたいと思いそう書いたのですが。
yambejp

2018/05/24 02:44

dataのフィルタリング中にdataでうけても 「僕はdataの中身を入れ替えたい」を実現できないからです 別途抽出したnew_dataをつかって、作業後に上書きをすればよいでしょう data=new_data;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問