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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

5回答

720閲覧

JavaScript 配列 重複した列を足して返したい

zeeee

総合スコア5

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2020/03/27 03:25

前提・実現したいこと

JavaScriptで配列の変換をしたい

該当のソースコード

最初の配列

javascript

1let data = [["a","b",10],["a","b",20],["a","c",30],["a","c",40],["a","d",50]];

結果

javascript

1[["a","b",30],["a","c",70],["a","d",50];

data[0]とdata[1]が一致した時に,data[2]を足した配列を返したいです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

すでにベストアンサーが決まった後に失礼します。

考え方

この回答では、考え方として以下の1.〜 **4. **の考え方によるアプローチを採ります。

**1.**説明の便宜上、data の要素である配列(例: ["a","b",10] )について、
・末尾の要素を除いた配列(例: ["a", "b"] )を、キー配列と呼ぶ。
・末尾の要素(例: 10) のことを、単に 数値 と呼ぶ。

**2.**所与の data から、まず以下の2点を作成
(ⅰ)totals:各キー配列別の数値の合計が格納されたオブジェクト
(ⅱ)keysdata の要素に出現するキー配列を、出現順に、かつ、重複なく含む配列

**3.**上記2.(ⅰ)のオブジェクト totals には、キー配列が例えば ["a", "b"] である数値の合計(ご質問にあるサンプルだと 30)が totals.a.b に格納されるようにする。
・従って、ご質問の例だと、 totals は以下のようなオブジェクトになる。

javascript

1// totals の例 2{ a: { b: 30, c: 70, d: 50 } }

**4.**オブジェクト totalskeys から、結果として望ましい形式の配列 result を得る。

コード例

以下は、上記の考え方によるコードです。配列やオブジェクトの操作で便利なライブラリ lodash を使用しています。

javascript

1 2const [totals, keys] = data.reduce(([obj, keys], ary) => { 3 const [k, v] = [_.initial(ary), _.last(ary)]; 4 if (_.has(obj, k)) { 5 _.set(obj, k, _.get(obj, k) + v); 6 } 7 else { 8 _.set(obj, k, v); 9 keys.push(k); 10 } 11 return [obj, keys]; 12}, [{}, []]); 13 14const result = keys.map(k => [...k, _.get(totals, k)]);

上記のコードで使っている lodash のメソッドは以下です。

  • totalsのキー配列に対する値の取得、設定および存在確認: _.get, _.set, _.has
  • 配列から最後の要素を取得: _.last
  • 配列から最後の要素を除いた配列の取得: _.initial

 

 

以下は、上記のコードを動作確認するためのサンプルです。動作確認のため、dataに要素を追加しています。

以上、参考になれば幸いです。

投稿2020/03/27 18:03

編集2020/03/29 01:01
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

new Map()と分割代入の練習で作ってみました。

js

1let data = [["a", "b", 10], ["a", "b", 20], ["a", "c", 30], ["a", "c", 40], ["a", "d", 50], ["a", "b", "c", 50], ["a", "b", "c", 50]]; 2//[["a","b",30],["a","c",70],["a","d",50]; 3 4const aggregate = new Map(); 5data.forEach(keys_value => { 6 const value_keys = Array.from(keys_value); 7 value_keys.unshift(value_keys.pop()); 8 const [value, ...keys] = [...value_keys]; 9 aggregate.set(JSON.stringify(keys), (aggregate.get(JSON.stringify(keys)) || 0) + value); 10}); 11 12const result = [...aggregate.entries()].map(v => [...JSON.parse(v[0]), v[1]]); //[ [ "a", "b", 30 ], [ "a", "c", 70 ], [ "a", "d", 50 ], [ "a", "b", "c", 100 ] ] 13console.log(result);

json

1 [ [ 'a', 'b', 30 ], 2 [ 'a', 'c', 70 ], 3 [ 'a', 'd', 50 ], 4 [ 'a', 'b', 'c', 100 ] ]

投稿2020/03/27 15:41

編集2020/03/28 02:04
oikashinoa

総合スコア2826

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

複雑なので綺麗に収まりませんね。

js

1const data = [ 2 ["a","b",10], 3 ["a","b",20], 4 ["a","c",30], 5 ["a","c",40], 6 ["a","d",50] 7]; 8const result = Object.entries( 9 data 10 .map(([k1, k2, num]) => [`${k1}.${k2}`, num]) 11 .reduce((o, [k, num]) => ({...o, [k]: (o[k] || 0) + num}), {}) 12).map(([key, num]) => [...key.split('.'), num]); 13 14console.log(JSON.stringify(result, null, 2));

JSON

1[ 2 [ 3 "a", 4 "b", 5 30 6 ], 7 [ 8 "a", 9 "c", 10 70 11 ], 12 [ 13 "a", 14 "d", 15 50 16 ] 17]

投稿2020/03/27 05:06

miyabi-sun

総合スコア21203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/03/27 05:41

文字列の連結で処理するのは微妙ですね セパレータを予約語としてきちんと仕様提示しないと バグに繋がります
miyabi-sun

2020/03/27 05:59

そうですね、プロの現場なら確実に共有・確認しておくべき事項ですね。 私はキー情報候補になる文字列には`.`は使わないみたいなローカルルールを付与することが多いですかね。 `["a", "b"] === ["a", "b"]`の結果が`false`になるような言語ですし、 ガチで作るなら修正欄で死ぬほど詰めまくる必要があります。 じゃあ最初から回答するなよみたいな感じになりますので、 質問文の状況から必要最小限のコードで良いんじゃない?くらいに考えて回答に起こしました。
yambejp

2020/03/27 06:03

微妙なだけで絶対ダメとは思いません。 「配列内にピリオドを含む文字を入れてはいけません」 と注記があれば大丈夫でしょう。 もしくはなんらかのセパレータをユーザーが指定できるようにするとか 調整次第ですかね・・・
guest

0

javascript

1const data = [["a","b",10],["a","b",20],["a","c",30],["a","c",40],["a","d",50]]; 2const o = data.reduce((a,c)=> a[c[0]] ? (a[c[0]][c[1]] ? {...a, [c[0]]:{...a[c[0]],[c[1]]: a[c[0]][c[1]] + c[2]} }: {...a, [c[0]]:{...a[c[0]],[c[1]]:c[2]}}) : {...a, [c[0]]:{[c[1]]:c[2]} },{}); 3const p = Object.keys(o).reduce((a,c) => a.concat([Object.keys(o[c]).map(e=>[c,e,o[c][e]])]),[]); 4console.log(p);

group をつくって、展開すると考えました。

投稿2020/03/27 04:18

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

思ったよりグダグダになったので、最適解は他の回答者におまかせします

投稿2020/03/27 03:57

yambejp

総合スコア116724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/03/27 03:57

var data = [["a","b",10],["a","b",20],["a","c",30],["a","c",40],["a","d",50]]; var res=[...data.reduce((x,y)=>(x.add(JSON.stringify([y[0],y[1]])),x),new Set())] .map(x=>JSON.parse(x)) .map(x=>[x[0],x[1],data.filter(y=>x[0]==y[0]&&x[1]==y[1]).reduce((x,y)=>x+y[2],0)]); console.log(res);
yambejp

2020/03/27 03:58

あとa,bとb,aが一緒かどうかでも結果は変わってきます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問