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

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

ただいまの
回答率

90.34%

  • JavaScript

    17604questions

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

  • jQuery

    7126questions

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

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

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 370

k0908

score 85

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配列に入れるにはどうしたらいいか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

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

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" } ] }
};

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

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

var 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'},
    ]
  };
var young ="12";
var old ="59";
var new_data={};
Object.keys(data).forEach(function(x){
  var y=data[x].filter(function(x){
    return parseInt(x["a2"])>=parseInt(young) && parseInt(x["a2"])<=parseInt(old);
  }).sort(function(x,y){
    return x["a2"]==y["a2"]?0:(parseInt(x["a2"])<parseInt(y["a2"])?1:-1);
  });
  if(y.length>0) Object.defineProperty(new_data, x, {value:y}); /*修正*/
});     
data=new_data;
console.log(data);


一部修正しました

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/24 11:39

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

    キャンセル

  • 2018/05/24 11:44

    dataのフィルタリング中にdataでうけても
    「僕はdataの中身を入れ替えたい」を実現できないからです

    別途抽出したnew_dataをつかって、作業後に上書きをすればよいでしょう
    data=new_data;

    キャンセル

+1

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


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"という降順ソートになっているのが想定した動作なのか(ソートするとは書いていてもソートの要件は明示されていません)もあわせてご確認いただいたほうがいいかもしれません

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

やりたいことは

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

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

const 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 }],
};

const ageFilter = v => (v.a2 >= 12 && v.a2 <= 59);
const sort = (a, b) => (b.a2 - a.a2);

const result = Object.fromEntries(Object.entries(data).map(([key, value]) => {
  const sortedData = value.sort(sort);
  const filteredData = sortedData.filter(ageFilter);
  if (filteredData.length) {
    return [[key]: filteredData];
  }
  return [[key]: value];
}));

console.log(result);

Object.fromEntries は stage0 の実験段階中
https://tc39.github.io/proposal-object-from-entries/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • JavaScript

    17604questions

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

  • jQuery

    7126questions

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