前提・実現したいこと
配列(arr)の中に含まれている一つ一つの値が、
オブジェクト(obj)の中にどのくらい含まれているか、その数を返したいと思っています。
該当のソースコード
const arr = [hoge, fuga, piyo] const obj = { "tasks": [ { "id": 1, "item": “piyo” }, { "id": 2, "item": “hoge” }, { "id": 3, "item": “piyo” }, { "id": 4, "item": “fuga” }, { "id": 5, "item": “hoge” }, { "id": 6, "item": “piyo” } ] } // ↓↓↓ // 期待する戻り値 // hoge: 2 // fuga: 1 // piyo: 3
返される値は、オブジェクトでもなんでもいいのですが
たとえば、 {hoge:2, fuga:1, piyo:3}
この個数を出すには、JavaScriptをどう組むのがスマートなのでしょうか?
(underscore等のライブラリは、訳あって使えないので、 ネイティブのJsで組みたいと思っています)
ヒントだけでもご教示いただけますと助かります。
何卒宜しくお願いたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
js
1const r = obj.tasks.reduce((o, t) => { 2 o[t.item] = o[t.item] + 1 || 1 3 return o 4}, {}) 5 6// or 7 8const r2 = {} 9obj.tasks.forEach(t => { 10 r2[t.item] = r2[t.item] + 1 || 1 11})
投稿2018/07/18 23:47
総合スコア849
0
こんにちは。
sii_side さんのご回答にある reduce
を使い、さらに結果として得られるオブジェクトとして、Map を使うことにすると、Map
の setメソッドがレシーバのMap
オブジェクトを返してくれることを利用して、以下のように、reduce
の第1引数に渡す関数本体で return
が不要になります。
[jun68ykt@macbook ~]$ node -v
v9.6.1
[jun68ykt@macbook ~]$ cat tera136707.js
javascript
1const obj = { 2 tasks: [ 3 { id: 1, item: 'piyo' }, 4 { id: 2, item: 'hoge' }, 5 { id: 3, item: 'piyo' }, 6 { id: 4, item: 'fuga' }, 7 { id: 5, item: 'hoge' }, 8 { id: 6, item: 'piyo' } 9 ] 10}; 11 12const counts = obj.tasks.reduce( 13 (m, t) => m.set(t.item, (m.get(t.item) || 0) + 1), 14 new Map() 15); 16 17console.log(counts);
[jun68ykt@macbook ~]$ node tera136707.js
Map { 'piyo' => 3, 'hoge' => 2, 'fuga' => 1 }
[jun68ykt@macbook ~]$
以上、参考になれば幸いです。
追記
コメントから頂戴した、以下の質問に回答します。
●質問 => このアローが入ってきているのは、そういう仕様だということしょうか? piyoがkeyで、値が3という認識で合っていますでしょうか?
まず、
piyoがkeyで、値が3という認識で合っていますでしょうか?
については、はい、その認識で合ってます。
次に
=> このアローが入ってきているのは、そういう仕様だということしょうか?
については、そういう実装になっている、という解釈のほうがよいです。
より詳しくは、私の回答では node v9.6.1 でJSを実行したものなので、
node v9.6.1 では Mapオブジェクトを console.log で出力すると、 Map { 'piyo' => 3, 'hoge' => 2, 'fuga' => 1 } という風に、キーと値の対応を => を使った形式で出力するように、 console.log が作られている。
と考えたほうがよいです。
というのも、他の JavaScriptの実行環境(=わかりやすくいうと、他の場所で動くJavaScript)の中には、Mapオブジェクトをconsole.log
で出力したときに、キーと値との対応を =>
ではない記号で表しているものも、あり得るからです。
例えば、以下のようなJSを含むHTMLを作ります。
html
1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <title>Q136707</title> 6 <script> 7 document.addEventListener("DOMContentLoaded", function(event) { 8 const obj = { 9 tasks: [ 10 { id: 1, item: 'piyo' }, 11 { id: 2, item: 'hoge' }, 12 { id: 3, item: 'piyo' }, 13 { id: 4, item: 'fuga' }, 14 { id: 5, item: 'hoge' }, 15 { id: 6, item: 'piyo' } 16 ] 17 }; 18 19 const counts = obj.tasks.reduce( 20 (m, t) => m.set(t.item, (m.get(t.item) || 0) + 1), 21 new Map() 22 ); 23 24 console.log(counts); 25 }); 26 </script> 27</head> 28<body> 29 30</body> 31</html>
そして、上記HTMLをMac版Firefox の最新バージョン(v61.0.1)で表示し、開発ツールを開いたところが以下です。
上記で分かるとおり、=>
ではなく、 →
が使われているので、
Mac版Firefox の最新バージョン(v61.0.1)に組み込まれたJavaScript処理系では、 Mapオブジェクトを console.log で表示すると、 Map(3) { piyo → 3, hoge → 2, fuga → 1 } と表示するように、 console.log が作られている。
と言えます。
余談ですが、マップや連想配列やハッシュといった、キーと値の組を持つデータ構造を、(表示するときではなく)プログラムの中で定義するのに、 =>
を使う言語があります。
たとえばRubyでは
ruby
1counts = { 'piyo'=>3, 'hoge'=>2, 'fuga'=>1 }
と書きますし、PHPでは以下です。
php
1$counts = [ 'piyo'=>3, 'hoge'=>2, 'fuga'=>1 ];
ですので、 JavaScript で Mapオブジェクトを console.log で出力したとき
=>
が使われるのは、RubyやPHPを知っている人にとっては、自然な(というか見慣れた)
感じがすることでしょう。
投稿2018/07/19 02:13
編集2018/07/19 13:07総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/07/19 12:28
2018/07/19 23:06
0
単純にループを回してカウントして行ってはいかがですか?
そういうのは質問者さんが言う「スマート」ではないから NG と言うことでしたら、その辺りをもう少し詳しく説明ください。
投稿2018/07/18 23:17
退会済みユーザー
総合スコア0
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/07/19 00:08