以下のような連想配列(オブジェクト)があるとする。
input.js
var array = [
{key1:'aa', key2:'b', code:'c'},
{key1:'a', key2:'b', code:'d'},
{key1:'aa', key2:'bb', code:'e'},
{key1:'a', key2:'bb', code:'f'},
{key1:'aa', key2:'bb', code:'g'},
]
やりたいこと
これを、key1が同じものでまとめて、さらに、key2が同じものでまとめる。
連想配列の下に、連想配列を持ち、codeが同じなら配列にする。
結果的に以下のような形にしたい。
result.js
array = {
aa:{
b:['c'],
bb:['e','g']
},
a:{
b:['d'],
bb:['f']
}
}
試行錯誤した結果、以下のようなコードになったが、 できれば、mapやreduce,filterなど使って、もう少しスマートに書きたかった。
app.js
var newArr = {};
array.forEach(function(data) {
var key1 = data['key1'];
var key2 = data['key2'];
var code = data['code'];
var obj = {};
if(newArr[key1] == undefined) {
newArr[key1] = obj; // ---- ①
// 未定義ならそのままcodeを入れる
if(newArr[key1][key2] == undefined) {
newArr[key1][key2]=[code];
console.log(key1+key2+code+'-----1');
}else{
// key2の中身は配列なので、そのままpushする
newArr[key1][key2].push(code); // ------ ②
console.log(key1+key2+code+'-----2');
}
}else{
if(newArr[key1][key2]==undefined){
newArr[key1][key2]=[code];
console.log(key1+key2+code+'-----3');
}else{
newArr[key1][key2].push(code);
console.log(key1+key2+code+'-----4');
}
}
});
console.log(newArr);
array = newArr;
コンソールに表示される順番として、1,1,3,3,4となる。
悩んだところ
①参照
いきなり、newArr[key1][key2];
のように書くと、下のようなエラーが出るので、①のようにした。
Uncaught TypeError: Cannot read property 'b' of undefined
if文のundefindのところを、''やnullとしていて、うまくいかなかった。
②参照
key1の中身が連想配列なので、key2の中に値を追加するときに、ずっと
obj = {[key2]:code};
Object.keys(newArr[key1][key2]).push(obj);
obj = {[key2]:code};
newArr = Object.assign(newArr[key1],obj);
のようなことをしていたので、うまくいかなかった。