まぁ今回のケースは確かに配列→配列なので、
まともに戦うと相当辛いでしょう。
私のような上級者になればLodashなど使わなくてもreduceで一撃ですけど、
相応にコードが汚れるので「日本語でおk」と言いたくなることでしょう。
というわけで値の加工がしたければLodashを覚えてください。
このやり方は関数型言語を始めとする多くのモダンな言語へ持っていける概念です。
つまり、Lodashの機能を全て読み込む事でモダンなエンジニアとしての能力が開花します。
nameが同じものでdescriptionを配列にまとめる
LodashではgroupByという機能で実現できます。
Online Lodash Testerで挙動を確認できます。
JavaScript
1// _.groupBy(配列, fn)
2// fn: 戻り値が文字列になる関数
3
4const fees = [
5 {name: '特別', description: `3,000円`},
6 {name: '特別', description: `100,000円`},
7 {name: 'ロイヤル', description: 'ロイヤル1'},
8 {name: '特別', description: `6,000円`},
9 {name: '普通', description: '普通1'},
10 {name: 'ロイヤル', description: 'ロイヤル2'},
11 {name: '普通', description: '普通2'},
12];
13result = _.groupBy(fees, it => it.name);
JSON
1{
2 "特別": [
3 {
4 "name": "特別",
5 "description": "3,000円"
6 },
7 {
8 "name": "特別",
9 "description": "100,000円"
10 },
11 {
12 "name": "特別",
13 "description": "6,000円"
14 }
15 ],
16 "ロイヤル": [
17 {
18 "name": "ロイヤル",
19 "description": "ロイヤル1"
20 },
21 {
22 "name": "ロイヤル",
23 "description": "ロイヤル2"
24 }
25 ],
26 "普通": [
27 {
28 "name": "普通",
29 "description": "普通1"
30 },
31 {
32 "name": "普通",
33 "description": "普通2"
34 }
35 ]
36}
これだけでは目的の値にはなりませんが、
特定のルールに従った配列を作るという目的では確実に前進しています。
引き続き別の値加工を行うために次の章へ行きましょう。
JavaScriptはそもそもArray->Arrayであればmapというメソッドがあるので簡単に加工出来るのですが、
groupByで作った値はオブジェクトなのでmapメソッドを所持していません。
まぁ、Object.entries()等は持っていますから配列を経由してやれば良いだけなのですが……
Lodashを利用する場合は、
オブジェクトに対してもmapが使えます。
カテゴリが配列を示すListではなく、オブジェクトも両対応のCollectionになっている所からも分かります。
また、Lodashは_.メソッド(値, fn)
で数珠つなぎにするとコードが非常に汚くなるので、
チェーン記法に対応しています。
JavaScript
1const fees = [
2 {name: '特別', description: `3,000円`},
3 {name: '特別', description: `100,000円`},
4 {name: 'ロイヤル', description: 'ロイヤル1'},
5 {name: '特別', description: `6,000円`},
6 {name: '普通', description: '普通1'},
7 {name: 'ロイヤル', description: 'ロイヤル2'},
8 {name: '普通', description: '普通2'},
9];
10result = _.chain(fees)
11 .groupBy(fee => fee.name)
12 .map((fees, name) => ({
13 name: name,
14 description: fees.map(fee => fee.description)
15 }))
16 .value();
JSON
1[
2 {
3 "name": "特別",
4 "description": [
5 "3,000円",
6 "100,000円",
7 "6,000円"
8 ]
9 },
10 {
11 "name": "ロイヤル",
12 "description": [
13 "ロイヤル1",
14 "ロイヤル2"
15 ]
16 },
17 {
18 "name": "普通",
19 "description": [
20 "普通1",
21 "普通2"
22 ]
23 }
24]
【おまけ】 reduceで一撃
まぁ、groupByのパターン知ってるエンジニアなら楽勝ですね。
reduceで似たようなものを再現するだけです。
(for文でちくちくやっても良いですが、状態変数が増えて読みづらくなるので一長一短)
ついでに配列ではなくdescriptionの文字列を抜き出した配列を作ってしまえば計算量が減ります。
さらっと書けるようになるためにもLodashは覚えて損はありません。
ぜひ
JavaScript
1const fees = [
2 {name: '特別', description: `3,000円`},
3 {name: '特別', description: `100,000円`},
4 {name: 'ロイヤル', description: 'ロイヤル1'},
5 {name: '特別', description: `6,000円`},
6 {name: '普通', description: '普通1'},
7 {name: 'ロイヤル', description: 'ロイヤル2'},
8 {name: '普通', description: '普通2'},
9];
10const result = Object.entries(
11 fees.reduce((obj, fee) => {
12 if (obj[fee.name] == null) obj[fee.name] = [];
13 obj[fee.name].push(fee.description);
14 return obj;
15 }, {})
16).map(([name, description]) => ({name, description}));
17
18console.log(JSON.stringify(result, null, 2));
JSON
1[
2 {
3 "name": "特別",
4 "description": [
5 "3,000円",
6 "100,000円",
7 "6,000円"
8 ]
9 },
10 {
11 "name": "ロイヤル",
12 "description": [
13 "ロイヤル1",
14 "ロイヤル2"
15 ]
16 },
17 {
18 "name": "普通",
19 "description": [
20 "普通1",
21 "普通2"
22 ]
23 }
24]