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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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
総合スコア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 の実験段階中
投稿2018/05/24 03:01
総合スコア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
総合スコア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総合スコア114779
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。