[["a",10], ["b",20], ["c",30], ["a",40], ["a",50]]
このような配列の
1つめの要素が一致する場合
2つめの要素の数値を合算した配列を作りたいのです。
(この場合はaの数値をまとめたい)
▼期待する形
[["a",100], ["b",20], ["c",30]]
こういった場合、みなさんがどのように実装しているのか
ご教授いただければ幸いです。
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
最近はRamdaにはまっています。
JavaScript
1var R = require("ramda"); 2var data = [["a",10],["b",20],["c",30],["a",40],["a",50]]; 3var result = R.toPairs(R.map(R.pipe(R.map(R.last), R.sum), R.groupBy(R.head, data))); 4console.log(result); // => [ [ 'a', 100 ], [ 'b', 20 ], [ 'c', 30 ] ]
関数型プログラミングは難しいです。もうちょっとすっきり書ける方法があるような気がします。
さらに関数型プログラミングっぽくしてみました。関数にしたから、再利用も可能です。
JavaScript
1var R = require("ramda"); 2var data = [["a",10],["b",20],["c",30],["a",40],["a",50]]; 3var mapSum = R.pipe(R.groupBy(R.head), R.map(R.pipe(R.map(R.last), R.sum)), R.toPairs); 4console.log(mapSum(data)); // => [ [ 'a', 100 ], [ 'b', 20 ], [ 'c', 30 ] ]
投稿2015/11/30 14:57
編集2015/12/01 10:31総合スコア21739
0
ベストアンサー
この状況で躓いてるようでしたら、Array#map
等の関数を使わず、for
文でコードを書いてみる事をお勧めします。
まず、頭の中でアルゴリズムを組み立てられるようになる事が重要ですが、その場合は for
文で地道に組んだほうが頭に入りやすいと思います。
Array#map
を使った手法は for
文の手法を習得してから覚えても遅くはありません。
JavaScript
1'use strict'; 2/** 3 * Array.prototype.indexOf 版 4 */ 5function sample_indexOf (array) { 6 var keys = [], 7 values = [], 8 results = []; 9 10 for (var i = 0, l = array.length, element, index; i < l; ++i) { 11 element = array[i]; 12 index = keys.indexOf(element[0]); 13 14 if (index !== -1) { 15 values[index] += element[1]; 16 } else { 17 keys.push(element[0]); 18 values.push(element[1]); 19 } 20 } 21 22 for (var i = 0, l = keys.length; i < l; ++i) { 23 results.push([keys[i], values[i]]); 24 } 25 26 return results; 27} 28 29/** 30 * ObjectLiteral 版 31 */ 32function sample_ObjectLiteral (array) { 33 var map = {}, 34 results = []; 35 36 for (var i = 0, l = array.length, element, key; i < l; ++i) { 37 element = array[i]; 38 key = element[0]; 39 40 if (map.hasOwnProperty(key)) { 41 map[key] += element[1]; 42 } else { 43 map[key] = element[1]; 44 } 45 } 46 47 for (var keys = Object.keys(map), i = 0, l = keys.length; i < l; ++i) { 48 results.push([keys[i], map[keys[i]]]); 49 } 50 51 return results; 52} 53 54/** 55 * Map 版 (ES6) 56 * @url https://github.com/paulmillr/es6-shim 57 */ 58function sample_map (array) { 59 var map = new Map, 60 results = []; 61 62 for (var i = 0, l = array.length, element, key; i < l; ++i) { 63 element = array[i]; 64 key = element[0]; 65 66 map.set(key, map.has(key) ? map.get(key) + element[1] : element[1]); 67 } 68 69 for (var iterator = map.entries(), i = 0, l = map.size; i < l; ++i) { 70 results.push(iterator.next().value); 71 } 72 73 return results; 74} 75 76/** 77 * Array.prototype.forEach + Array.prototype.find 版 (ES6) 78 */ 79 var sample_forEach = (function (findfn) { 80 function eachfn (element) { 81 var existingElement = this.find(findfn, element[0]); 82 83 if (typeof existingElement !== 'undefined') { 84 existingElement[1] += element[1]; 85 } else { 86 this.push(element); 87 } 88 } 89 90 return function sample_forEach (array) { 91 var results = []; 92 93 array.forEach(eachfn, results); 94 return results; 95 }; 96}(function findfn (element) { 97 return element[0] === this; 98})); 99 100/** 101 * Array.prototype.reduce + + Array.prototype.find 版 (ES6) 102 */ 103var sample_reduce = (function (findfn) { 104 function reducefn (previous, current){ 105 var existingElement = previous.find(findfn, current[0]); 106 107 if (typeof existingElement !== 'undefined') { 108 existingElement[1] += current[1]; 109 } else { 110 previous.push(current); 111 } 112 113 return previous; 114 } 115 116 return function sample_reduce (array) { 117 return array.reduce(reducefn, []); 118 } 119}(function findfn (element) { 120 return element[0] === this; 121})); 122 123var array = [['a',10], ['b',20], ['c',30], ['a',40], ['a',50]]; 124 125console.log(JSON.stringify(sample_indexOf(array))); // [["a",100],["b",20],["c",30]] 126console.log(JSON.stringify(sample_ObjectLiteral(array))); // [["a",100],["b",20],["c",30]] 127console.log(JSON.stringify(sample_map(array))); // [["a",100],["b",20],["c",30]] 128console.log(JSON.stringify(sample_forEach(array))); // [["a",100],["b",20],["c",30]] 129console.log(JSON.stringify(sample_reduce(array))); // [["a",100],["b",20],["c",30]]
個人的には ES6 の Map
で map
オブジェクトを返す仕様に変更する事がお勧めです。
が、new Map
は "es6-shim" 等の polyfill を使わないとクロスブラウザが出来なく、サンプルコードも少ない為、今すぐに習得しなくても良いと思います。
実際のところは ObjectLiteral
で上手くいくケースが大半です。
- Array.prototype.indexOf() - JavaScript | MDN
- Object.prototype.hasOwnProperty() - JavaScript | MDN
- Object.keys() - JavaScript | MDN
- Map - JavaScript | MDN
- Array.prototype.forEach() - JavaScript | MDN
- Array.prototype.reduce() - JavaScript | MDN
- Array.prototype.find() - JavaScript | MDN
- paulmillr/es6-shim
- ECMAScript 6 compatibility table
(2015/12/04 23:07追記)
Array#forEach
, Array#reduce
, Array#find
を使ったコードを追記しました。
Re: kado_ さん
投稿2015/12/01 05:16
編集2015/12/04 14:07総合スコア18189
0
ここでLiveScriptを使って参戦!
[["a",10],["b",20],["c",30],["a",40],["a",50]] |> group-by (.0) |> Obj.map -> it |> map (.1) |> fold1 (+) |> obj-to-pairs # [["a",100],["b",20],["c",30]]
わぁい、たったの4行!
http://livescript.net/ ←右側のミニコンソールでお試しあれ
投稿2015/12/03 15:05
編集2015/12/03 23:24総合スコア21203
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/12/03 15:35
2015/12/03 21:55
2015/12/03 23:31 編集
2015/12/04 14:23
0
まず coffeescript で書いてみました。次にそれを coffee -pb で javascript にしてみました。
coffeescript
1data = [["a",10], 2["b",20], 3["c",30], 4["a",40], 5["a",50]]; 6 7h = {} 8for d in data 9 key = d[0] 10 if h[key] 11 h[key] += d[1] 12 else 13 h[key] = d[1] 14 15ans = [] 16for key, val of h 17 ans.push [key, val] 18 19console.log ans
実行結果
coffee 1.coffee [ [ 'a', 100 ], [ 'b', 20 ], [ 'c', 30 ] ]
$ coffee -pb 1.coffee > 1.js $ node 1.js [ [ 'a', 100 ], [ 'b', 20 ], [ 'c', 30 ] ] $ cat 1.js var ans, d, data, h, i, key, len, val; data = [["a", 10], ["b", 20], ["c", 30], ["a", 40], ["a", 50]]; h = {}; for (i = 0, len = data.length; i < len; i++) { d = data[i]; key = d[0]; if (h[key]) { h[key] += d[1]; } else { h[key] = d[1]; } } ans = []; for (key in h) { val = h[key]; ans.push([key, val]); } console.log(ans);
投稿2015/11/30 13:22
編集2015/11/30 19:13総合スコア22324
0
普通な感じで。
javascript
1(function (arr){ 2 return arr.map(function(elm){ 3 return elm[0]; 4 }) 5 .filter(function(elm, i, self){ 6 return i == self.indexOf(elm); 7 }) 8 .map(function(key){ 9 return [key, arr.reduce(function(sum, elm){ 10 return sum += elm[0] == key ? elm[1] : 0; 11 },0)]; 12 }) 13})( 14 [["a",10], 15 ["b",20], 16 ["c",30], 17 ["a",40], 18 ["a",50]] 19);
ついでにfirefoxじゃないと動かない書き方で。
javascript
1(function(arr){ 2 return [ 3 [x, arr.reduce(function(sum, [k, v]){ 4 return sum += k==x ? v : 0; 5 }, 0)] 6 for 7 (x of new Set( 8 [ k for each ([k, ] in arr ) ] 9 )) 10 ] 11})([ 12 ["a",10], 13 ["b",20], 14 ["c",30], 15 ["a",40], 16 ["a",50] 17]);
投稿2015/12/01 01:08
編集2015/12/01 01:52総合スコア36963
0
対象要素Aと同じワードを持つ要素Bを検索し、見つけたらBの値をAに加算しBを破壊していくババ抜き的方法。
JavaScript
1var data = [["a",10], ["b",20], ["c",30], ["a",40], ["a",50]]; 2 3for(var i = 0; i < data.length; i++){ 4 for(var j = i+1; j < data.length; j++){ 5 6 if(data[i][0] == data[j][0]){ 7 8 data[i][1] += data[j][1]; 9 data.splice(j--, 1); 10 } 11 } 12} 13 14console.log(data);
spliceの負荷が気になる。
投稿2015/11/30 15:23
総合スコア144
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/12/01 05:41