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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

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

Q&A

解決済

2回答

1728閲覧

【Google Apps Script】配列から特定の列が同じデータをまとめて新しい配列に格納したい

akarinrin

総合スコア33

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

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

0グッド

0クリップ

投稿2019/05/02 04:31

前提・実現したいこと

スプレッドシート上でピポットテーブルを作るイメージで、
商品コード(arr[0])が同じものの販売数の合計と実績の日数(データの数)を取得したいです。

元の配列:日ごとの販売実績
商品コード,販売数
[a001,1]
[a001,2]
[a001,3]
[a001,4]
[b002,1]
[b002,2]
[b002,3]
[b002,1]
[c003,1]

欲しい配列:商品コードでまとめた販売実績
商品コード,合計販売数,実績日数
[a001,10,4]
[b002,7,4]
[c003,1,1]

ご教授の程よろしくお願いいたします。

また可能であれば、元のデータの2次元配列の列数が3列でも10列でも対応できるような
関数ができれば望ましいのですが、可能なのでしょうか?
元データの配列はn行m列で、計算されて得られる配列はn行m+1列で取得できればすごくいいです。

発生している問題・エラーメッセージ

正しく計算されない

該当のソースコード

GAS

1//@param {Ary} ary 元データ(2次元配列) 2//@param {Number} col 基準となる列番号 3//@return {Ary} ary_return 基準で合計したデータ(2次元配列) 4function totaling_ary(ary, col){ 5 var ary_return = new Array(); 6 7 ary_return.push([ary[0][0], ary[0][1], 1]); 8 for(var i = 1; i < ary.length ; i++) { 9 for(var j = 0; j < ary_return.length ; j++) { 10 if(ary[i][0] == ary_return[j][0]){ 11 ary_return[j][1] += parseInt(ary[i][1]); 12 ary_return[j][2] ++; 13 break; 14 }else if(j == ary_return.length - 1){ 15 ary_return.push([ary[i][0], ary[i][1], 1]); 16 } 17 } 18 } 19 return ary_return; 20}

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

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

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

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

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

papinianus

2019/05/02 06:20

もとの配列が3列以上の場合、3列目以後はどう処理するのですか?全部合計するのですか? サンプルは10行2列から得られた結果がn-7行m+1列ですが、どういう動きが正しいのですか?
akarinrin

2019/05/02 06:48

コメントいただきましてありがとうございます! >>もとの配列が3列以上の場合、3列目以後はどう処理するのですか?全部合計するのですか? 3列以上の場合、先頭の元データのデータを保持する形で実装できればと思います。 元の配列:日ごとの販売実績 商品コード, 販売数, 販売日 [a001, 1, 4/5] [a001, 2, 4/6] [a001, 3, 4/8] [a001, 4, 4/11] [b002, 1, 4/11] [b002, 2, 4/12] [b002, 3, 4/6] [b002, 1, 4/26] [c003, 1, 4/6] 欲しい配列:商品コードでまとめた販売実績 商品コード, 合計販売数, 販売日, 実績日数 [a001, 10, 4/5, 4] [b002, 7, 4/11, 4] [c003, 1, 4/6, 1] >>サンプルは10行2列から得られた結果がn-7行m+1列ですが、どういう動きが正しいのですか? まとめられた分だけ行数が減らないとおかしいですね。 質問の仕方が悪くてすいません。。。 元データの配列:n 行 m 列 計算されて得られる配列:n - (まとめられた行数)行 m + 1 列 足りない情報などございましたら、おっしゃっていただけますと幸いです。 よろしくお願いします。
guest

回答2

0

ベストアンサー

試してないですが、多分Google App Scriptでも動作するであろうサンプルコードをかきました。

  • 2次元目の配列の個数は不定(3かもしれないし10かもしれない)が、一定の数で揃っている(3,4,3にはならない)
  • 1項目目をグルーピングのキーとする
  • 2項目目(数値)を合計する
  • 項目の最後に件数カウンタをつける

javascript

1const data = [["a001",1],["a001",2],["a001",3],["a001",4],["b002",1],["b002",2],["b002",3],["b002",1],["c003",1]] 2//const data = [["a001", 1, "4/5"], ["a001", 2, "4/6"], ["a001", 3, "4/8"], ["a001", 4, "4/11"], ["b002", 1, "4/11"], ["b002", 2, "4/12"], ["b002", 3, "4/6"], ["b002", 1, "4/26"], ["c003", 1, "4/6"]] 3// 所与のサンプルデータを配列にした例。例えばSpreadsheetApp.getActiveSheet().getDataRange().getValues();したと想定 4 5// キー項目でオブジェクトにする。グルーピング処理 6const obj = data.reduce(function(a,c) { if(a[c[0]]) { a[c[0]][0] += c[1]; a[c[0]][c.length - 1]++}else{a[c[0]] = c.slice(1).concat([1])} return a},{}) 7// オブジェクトを欲しいかたちの配列にする 8const result = Object.keys(obj).map(function(e) { return [e].concat(obj[e])}) 9Logger.log(result) // <-こちらでご確認ください

もし関数にしたければ

javascript

1function hatchpotch(data) { 2 const obj = data.reduce(function(a,c) { if(a[c[0]]) { a[c[0]][0] += c[1]; a[c[0]][c.length - 1]++}else{a[c[0]] = c.slice(1).concat([1])} return a},{}) 3 return Object.keys(obj).map(function(e) { return [e].concat(obj[e])}) 4}

として、var umaikotoyattayatu = hatchpotch(ary);と使えばよいと思います。

投稿2019/05/02 14:29

papinianus

総合スコア12705

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

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

akarinrin

2019/05/08 02:45

papinianusさん ご回答いただきありがとうございます! また返信が大変遅れまして申し訳ございません。
guest

0

修正ポイントとしてfor (var j = 0; j < ary_return.length ; j++) {のループ内にあるary_return.push([ary[i][0], ary[i][1], 1]);の一つ下の行にbreak;を追加するのは如何でしょうか。

追記

また可能であれば、元のデータの2次元配列の列数が3列でも10列でも対応できるような

上記の追加質問を失念しておりました。申し訳ありません。コメントにあるご希望の出力値から、3列目以降の値は出現した最初の値のみを結果に出力したいと理解しました。このような理解で問題がない場合、下記のような修正では如何でしょうか。

修正したスクリプト

javascript

1function totaling_ary(ary, col){ 2 var ary_return = new Array(); 3 4 ary_return.push([ary[0][0], ary[0][1]].concat(ary[0].slice(2, ary[0].length)).concat(1)); 5 for (var i = 1; i < ary.length ; i++) { 6 for (var j = 0; j < ary_return.length ; j++) { 7 if (ary[i][0] == ary_return[j][0]){ 8 ary_return[j][1] += parseInt(ary[i][1], 10); 9 ary_return[j][ary_return[j].length - 1] ++; 10 break; 11 } else if (j == ary_return.length - 1) { 12 ary_return.push([ary[i][0], ary[i][1]].concat(ary[i].slice(2, ary[i].length)).concat(1)); 13 break; 14 } 15 } 16 } 17 return ary_return; 18}
  • ご提示されたサンプルでは[a001, 1, 4/5], [a001, 2, 4/6], [a001, 3, 4/8], [a001, 4, 4/11]の場合、ご希望の出力は[a001, 10, 4/5, 4]とありましたので、さらに列が追加されると、[a001, 10, 4/5, 4][a001, 10, 4/5, sample1, sample2, 4]としたいのではないかと推測しました。推測が間違っているようならすみません。

投稿2019/05/02 06:16

編集2019/05/02 08:09
kisojin

総合スコア899

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

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

akarinrin

2019/05/02 06:30

ご回答いただきありがとうございます! ご助言の通りbreak;を追加すると希望通りの動作を致しました。 ありがとうございます!
kisojin

2019/05/02 08:09

ご返事ありがとうございます。追加質問を失念しておりましたので追記致しました。ご確認お願い致します。
akarinrin

2019/05/08 02:46

kisojinさん 追加の回答もいただきましてありがとうございます! 返信が遅くなり大変申し訳ございません。 非常に助かりました。 ありがとうございます!
kisojin

2019/05/09 08:04

ご連絡有難うございます。無事解決したとのことで安心しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問