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

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

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

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

Q&A

解決済

2回答

3581閲覧

【Javascript】2次元配列からピボットテーブル用に整形した配列を生成するロジック

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

0クリップ

投稿2015/05/05 04:40

編集2015/05/06 03:30

目的

以下の様なCSVから2次元配列を作成後(サンプル1)、結果テーブルに組み込むために整形した2次元配列を生成したい。

CSVサンプル

lang

1Date,Category,A,B,C 22015/02,AAA,a,b,c 32015/02,BBB,d,e,f 42015/03,CCC,g,h,i 52015/03,BBB,j,k,l 62015/03,AAA,m,n,o

サンプル1

lang

1var csvArray = [ //サンプルのため値へのクォートは省略 2 [2015/02,AAA,a,b,c], 3 [2015/02,BBB,d,e,f], 4 [2015/03,CCC,g,h,i], 5 [2015/03,AAA,j,k,l] 6];

結果テーブル

lang

1Table AAA Table BBB Table CCC 2| |2015/02|2015/03| | |2015/02|2015/03| | |2015/02|2015/03| 3|:--|-------|------:| |:--|-------|------:| |:--|-------|------:| 4| A | a | j | | A | d | | | A | | g | 5| B | b | k | | B | e | | | B | | h | 6| C | c | l | | C | f | | | C | | i |

生成したい配列サンプル

lang

1var table = [ 2 [AAA,a,j,b,k,c,l], 3 [BBB,d,'',e,'',f,''], 4 [CCC,'',g,'',h,'',i] 5]; 6 7//オブジェクトでも構わない 8var table = { 9 'AAA':[a,j,b,k,c,l], 10 'BBB':[d,'',e,'',f,''], 11 'CCC':['',g,'',h,'',i] 12};

前提条件

  1. Javascript(jQuery等不可)使用
  2. 配列の1次元目は行方向、2次元目は列方向とし、2次元目の長さはすべて同じ
  3. データがないセルは空白('')とする
  4. Categoryごとにテーブル(配列)をまとめる
  5. 行列変換用の関数はmatrix(array)として定義されているものとする

(利用の有無は問わないが利用を前提とする)
6. tableの結果テーブル整形処理は実装済みとする

ピボットテーブル生成という表現が正しいかどうかは別としまして、
csvArrayから各テーブルにセットするための値をまとめたtableを生成するまでのロジックについて、
皆様のお知恵をお借りしたいと思っております。
サンプル通りの配列生成にこだわっているわけではございませんので、よろしくお願い致します。

補足

既に定義(実装)済みのmatrix関数は汎用化設計をしているという前提です。
単純に2次元配列を投げると行列変換された新しい2次元配列として返ってくるというものです。
要するにcsvArrayをtableに変換する過程において、必要ならばユーティリティーツールとしてご利用ください、といった感じです。

処理過程を文書にすると以下の様になります。

  1. CSVから配列Aを生成
  2. 配列Aを結果テーブル生成用に整形する(配列B)
  3. 配列Bを結果テーブルとして整形

1、3の前後の処理ありきで、中間部分の2のロジックを求めています。
全体の構造は以下のようになっていると考えてください。

構造サンプル

lang

1var csvArray = csvToArray(csv); 2/* ココカラ */ 3 4csvArrayをtableに変換する過程のロジックを求めています。 5 6/* ココマデ */ 7 8// 以降、tableを結果テーブルに整形処理(実装済み) 9 10function csvToArray(csv){ 11 処理 12 return array;//2次元配列を返す 13} 14function matrix(array){ 15 処理 16 return newArray;//行列変換後の新しい2次元配列を返す 17}

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

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

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

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

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

guest

回答2

0

ベストアンサー

自己解決、というより質問投稿する以前に持っていたイメージを再現したものです。
前後の処理は割愛しています。
以下のロジックでの最終出力結果はオブジェクトとなります。

lang

1var dateCol = matrix(csvArray)[0].filter(function(v,i,a){return (a.indexOf(v) == i);});//日付のユニーク配列(結果テーブルの列数としても利用(要+1)) 2var ctgry = matrix(csvArray)[1].filter(function(v,i,a){return (a.indexOf(v) == i);});//カテゴリのユニーク配列(結果テーブル生成数としても利用) 3var rows = csvArray[0].length - 2;//結果テーブルのヘッダー行を除く必要行数 4var table = {}; 5var nAry = new Array(rows).join("''").split("''");//必要列数分を空値で埋めた配列。列数が多い場合はforループで処理 6 7/** 一旦カテゴリごとのオブジェクトにまとめる 8見通しを良くするためfor文を重ねて泥臭く処理 9ここでの肝はプロパティ値を2次元配列にすること 10 */ 11for(var i = 0,l = dateCol.length; i < l; i++) { 12 for(var j = 0,m = ctgry[0].length; j < m; j++) { 13 for(var k = 0,n = csvArray.length; k < n; k++){ 14 if(csvArray[k].indexOf(dateCol[i]) >= 0 && csvArray[k].indexOf(ctgry[j]) >= 0){ 15 table[ctgry[j]] ? 16 table[ctgry[j]].push(csvArray[k].slice(2)): 17 table[ctgry[j]] = [csvArray[k].slice(2)]; 18 break; 19 } 20 } 21 (k == n) && (table[ctgry[j]] ? table[ctgry[j]].push(nAry):table[ctgry[j]] = [nAry]); 22 } 23} 24 25/** オブジェクトの整形 */ 26for(i in table){ 27 var ary = matrix(table[i]); 28 table[i] = ary.join(',').split(','); 29 table[i].forEach(function(v,i,a){ 30 (v === void 0) && (v = "''"); 31 }); 32}

謝辞

htsign様、お忙しい中当方の質問へのご回答、ありがとうございました。
こちらで詳細を述べることはできませんが、その後仕様が若干変更され、求める配列の形式も変更となりました。
いただいた回答は今後の参考にさせていただきます。
ありがとうございました。

投稿2015/05/11 16:38

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

htsign

2015/05/13 11:55

for地獄ですね…。 今回は私の力不足でお助けできず残念でしたが、また機会がありましたらお力添えさせていただければと思います。
guest

0

書いてるうちにややこしくなってしまいました。

lang

1// 重複排除メソッド 2Array.prototype.distinct = function(){ 3 var ret = []; 4 5 for (var i = 0, l = this.length; i < l; i++) { 6 if (ret.indexOf(this[i]) !== -1) continue; 7 ret.push(this[i]); 8 } 9 return ret; 10}; 11 12var data = "\ 13Date,Category,A,B,C\n\ 142015/02,AAA,a,b,c\n\ 152015/02,BBB,d,e,f\n\ 162015/03,CCC,g,h,i\n\ 172015/03,BBB,j,k,l\n\ 182015/03,AAA,m,n,o"; 19 20var csvArray = createCsvArray(data, true); 21var table = matrix(csvArray); 22 23function createCsvArray(/* string */ data, /* bool */ headerVisible) { 24 headerVisible = !!headerVisible || false; 25 26 var lines = data.split("\n"); 27 28 if (headerVisible) { 29 lines.shift(); 30 } 31 return lines.map(function(line){ 32 return line.split(",").map(quote); 33 }); 34} 35 36function matrix(/* array */ array) { 37 // 2015/02, 2015/03 など、年月を取得 38 var monthes = array.map(function(arr){ return arr[0] }).distinct().sort(); 39 // AAA, BBB など、カテゴリ名を取得 40 var categories = array.map(function(arr){ return arr[1] }).distinct().sort(); 41 42 var table = {}; 43 categories.forEach(function(category){ 44 // targets はカテゴリ名に category を含んでいるもの 45 var targets = array.filter(function(arr){ return arr[1] === category }); 46 table[category] = []; 47 48 for (var i = 0; i < monthes.length; i++) { 49 targets 50 // 年月に montehs[i] を含むもののみ抽出 51 .filter(function(arr){ return arr[0] === monthes[i] }) 52 // 先頭2つ(年月とカテゴリ名)を削る 53 .map(function(arr){ return arr.slice(2) }) 54 .forEach(function(arr){ 55 for (var j = 0; j < arr.length; j++) { 56 table[category][j * monthes.length + i] = arr[j]; 57 } 58 }); 59 } 60 // undefined を '' に置き換え 61 for (var i = 0; i < table[category].length; i++) { 62 if (table[category][i] === void 0) { 63 table[category][i] = "''"; 64 } 65 } 66 }); 67 68 return table; 69} 70 71function quote(text) { 72 return "'" + text + "'"; 73}

投稿2015/05/05 07:11

htsign

総合スコア870

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

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

退会済みユーザー

退会済みユーザー

2015/05/05 09:36

htsign 様 ご回答頂きありがとうございます。 確かにややこしく、こんがらがりますね。。。お疲れ様です。 (特にmatorix内、filterからの、map、、からの、forEach、、、泣けてきます。) ただ、前提条件をもう少し詳しく記載しておけばよかったのかもしれませんが、 いただいたご回答で申しますと、createCsvArray及びmatrixは既に実装済み、 ということになります。 (matrixの利用の有無は問いませんが) その上で、「csvArrayから各テーブルにセットするための値をまとめたtableを生成するまでのロジック」を求めておりますので、 誠に申し訳ございませんが、厳密には当方の求める回答とは異なります。 しかしながら、ロジックの方向性や私自身あまり頻繁には使わないmapの利用法など、今後も含め参考にさせていただきます。 ありがとうございました。
htsign

2015/05/05 10:16

理解力が足らなくて失礼いたしました…。 > 行列変換用の関数はmatrix(array)として定義されているものとする ここを「定義されるものとする」と勝手に脳内変換してしまっていました。(実は条件を読み直すまで matrix関数は createTable関数 という名前にしていました) stshishoさんが必要としてらっしゃるのは変数 table からMarkdownで書かれたような結果テーブルを作るロジック、ということでしょうか? 私は「変数 csvArray を 変数 table に変換するロジック」を指していると考えていました。
退会済みユーザー

退会済みユーザー

2015/05/06 03:41

htsign 様 > 私は「変数 csvArray を 変数 table に変換するロジック」を指していると考えていました。 上記のご理解で間違いございません。 厳密に何が求めているものと違うか、というのはmatrix内で「変数 csvArray を 変数 table に変換」している点です。 詳しくは質問内容に補足として追加しましたが、既に実装されているmatrixをうまく使ってtableに変換したい、という内容です。 なお、私自身も処理イメージをもっておりますが、他の方のロジックも参考にしたいと思い、質問させている次第です。
htsign

2015/05/06 04:07

なるほど。そういうことでしたら、私の回答は「上記のmatrix関数の名前をcreateTableとしたもの」ということになります。 その上で > 要するにcsvArrayをtableに変換する過程において、必要ならばユーティリティーツールとしてご利用ください については「使わない」という選択をしたものをお考えいただければと思います。 stshishoさんも既にロジックはできているということですので、何かの参考にしていただければ幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問