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

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

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

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

配列

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

Q&A

解決済

5回答

425閲覧

複数の配列データを一つにまとめる方法について

morohey

総合スコア12

JavaScript

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

配列

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

0グッド

0クリップ

投稿2019/07/12 14:10

編集2019/07/13 16:53
  • **前提・実現したいこと **

JavaScriptで、複数の配列データを一つのデータにまとめ、CSVに出力するコードを書いています。
CSVに出力するためのコードは、JavaScript のデータを CSV で保存する内容 を参考にしています。
今回、自分が出力したい配列データは以下の通りです。

var data1 = [ [1,'A'], [2,'B'], [3,'C'] ]; var data2 = [ [4,'D'], [5,'E'], [6,'F'] ];
  • 実現したい表(CSV形式)
data1-numdata1-alphadata2-numdata2-alpha
1"A"4"D"
2"B"5"E"
3"C"6"F"
  • 改善したい点

上記の二つの配列データを一つのデータにまとめるにあたり、以下のコードを書いたのですが、配列の要素数が多くなっても対応できるような、もっと簡潔な書き方はないでしょうか。

var data = [ {'data1-num': data1[0][0],'data1-alpha': data1[0][1],'data2-num': data2[0][0],'data2-alpha': data2[0][1]}, {'data1-num': data1[1][0],'data1-alpha': data1[1][1],'data2-num': data2[1][0],'data2-alpha': data2[1][1]}, {'data1-num': data1[2][0],'data1-alpha': data1[2][1],'data2-num': data2[2][0],'data2-alpha': data2[2][1]}, ];

プログラミング初心者なもので非常に効率の悪いコードしか書けず、大変お恥ずかしいのですが、ご教授いただければ幸いです。

  • みなさま、ご回答ありがとうございました!

どの方の回答も発見と驚きの連続で、ベストアンサーを決めるのが大変難しかったです。初心者のわたくしに、真摯に対応してくださり、大変感動しております。ありがとうございました。

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

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

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

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

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

gentaro

2019/07/12 15:39

「実現はできているけど、コードに問題があると思っている」という意味でしょうか? であれば、「改善したい点」を質問文に書いて下さい。
morohey

2019/07/12 16:36

ご指摘ありがとうございます。わかりにくくてすみません。質問を編集いたしました。「実現はできているけど、もっと簡潔な書き方をご教授いただきたい」ということです。
guest

回答5

0

こんにちは。

この回答では、まず、ご質問に挙げられている、オブジェクトの配列 var dataと同じ内容の配列を作るためのコードを挙げます。その後、追記にて、よりCSVに近い配列を作るコードを示します。

ご質問の要件のうち、今後、何が変わる可能性があるのか?によって、書くコードが変わってくると思います。ご質問に挙げられている与件から、今後どうなる可能性があるのかを思いつくままに挙げてみると、以下が思いつきます。

ご質問に挙げられているコードでは、

  • data1data2 しかないが、data3, data4 ... と増える可能性がある。
  • data1data2 はともに要素の数が3で同じだが、いつも同じとは限らない。
  • data1およびdata2の要素は、どれも長さが2の配列であるが、今後、3以上になるかもしれない。(つまり、 num, alpha の次のサフィックスが追加されるかもしれない)
  • data1およびdata2の要素である配列は、どれも長さが2で同じ長さであるが、常にすべてが同じ長さとは限らない。

上記のような可能性が考えられますが、これらのうち、今後、何が変わるかもしれないのか(または、変わらないのか)がはっきりしていると、リファクタの方向性が決まります。

以下は、上記の可能性のどれであっても、修正すべき箇所がなるべく分かりやすいように、という考え方で作成したコードです。このコードで作られる data は、ご質問にある data と同じ内容の配列になります。

javascript

1const data1 = [ 2 [1,'A'], 3 [2,'B'], 4 [3,'C'] 5]; 6 7const data2 = [ 8 [4,'D'], 9 [5,'E'], 10 [6,'F'] 11]; 12 13const toObj = (ary, prefix) => ({ 14 [`${prefix}-num`]: ary[0], 15 [`${prefix}-alpha`]: ary[1] 16}); 17 18const dataObj = { data1, data2 }; 19 20const tmp = Object.entries(dataObj).map(([k, ary]) => ary.map(e => toObj(e, k))); 21 22const data = tmp[0].map((e,i) => ({...e, ...tmp[1][i]})); 23 24console.log(data); 25 26

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

追記

CSV を作るためにより適した配列ということでいえば、ご質問のコードにある data とは違う配列になりますが、以下のような配列のほうがよりCSVに近いと思います。

javascript

1[ 2 ["data1-num", "data1-alpha", "data2-num" ,"data2-alpha"], 3 [1,"A",4,"D"], 4 [2,"B",5,"E"], 5 [3,"C",6,"F"] 6]

そこで、上記のような配列を得るための、以下のような関数を作成しました。

javascript

1function makeCSVData(dataObj, columns) { 2 const keys = Object.keys(dataObj).sort(); 3 4 const lengths = keys.reduce((m, k) => m.set(k, Math.max(...dataObj[k].map(ary => ary.length))), new Map()); 5 6 const header = keys.reduce((ary, k) => 7 ary.concat([...Array(lengths.get(k))].map((_, i) => `${k}-${columns[i]}`)), []); 8 9 const numRows = Math.max(...Object.values(dataObj).map(ary => ary.length)); 10 11 const data = [...Array(numRows)].reduce((ary, _, i) => { 12 ary.push(keys.reduce((a, k) => 13 a.concat( 14 dataObj[k][i] ? 15 [...dataObj[k][i], ...Array(lengths.get(k) - dataObj[k][i].length ) ] : 16 [...Array(lengths.get(k))] 17 ) ,[])); 18 return ary; 19 }, 20 [header]); 21 22 return data; 23}

上記の関数 makeCSVData は以下のように使います。

javascript

1const data1 = [ 2 [1,'A'], 3 [2,'B'], 4 [3,'C'] 5]; 6 7const data2 = [ 8 [4,'D'], 9 [5,'E'], 10 [6,'F'] 11]; 12 13const data = makeCSVData({ data1, data2 }, ['num', 'alpha']);

この回答の冒頭に、入力データの様々な拡張性について書きましたが、上記の関数 makeCSVDataはそれらに対応しており、 以下のような入力でも適切に処理してCSV用のデータを生成します。

javascript

1const d1 = [ 2 [1,'A'], 3 [2,'B'], 4 [3,'C'], 5 [-1,'a'] 6]; 7 8const d2 = [ 9 [4,'D', true], 10 [5,'E'], 11 [6,'F', false, 100] 12]; 13 14const d3 = [ 15 [7,'X'], 16 [8,'Y'], 17 [9,'Z'], 18 [-7, 'x'], 19 [-8, 'y'] 20]; 21 22const data = makeCSVData({ d1, d2, d3 }, ['num', 'alpha', 'beta', 'gamma']);

関数 makeCSVDataは、ご質問で提示された与件の範囲をかなり超えた大袈裟なものになってしまいましたが、先の様々な入力の拡張に対応させようとすると、こういうコードになるという一例として参考にして頂ければと思います。

投稿2019/07/13 06:37

編集2019/07/14 02:33
jun68ykt

総合スコア9058

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

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

morohey

2019/07/13 17:09

jun68ykt様、ご回答ありがとうございます。 丁寧で良質なご回答に、ただただ感激しております。わたくしがあげたデータに対し、様々な可能性を提示してくださり、自分自身、データについての捉え方が画一的であったことに気がつきました。よりCSVに近い配列を作るコードも大変参考になりました。本当にありがとうございました。
jun68ykt

2019/07/13 20:11

どういたしまして。解決されたようでよかったです????
guest

0

reduceを使用すればもっと簡潔に書けます。
下記のコードであれば記述が明快なので
moroheyさんが見たときにわかりやすいかと。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

js

1var data1 = [ 2 [1,'A'], 3 [2,'B'], 4 [3,'C'] 5]; 6 7var data2 = [ 8 [4,'D'], 9 [5,'E'], 10 [6,'F'] 11]; 12 13var data = data1.reduce((a, c, i) => { 14 a.push({ 15 'data1-num': c[0], 16 'data1-alpha': c[1], 17 'data2-num': data2[i][0], 18 'data2-alpha': data2[i][1] 19 }); 20 return a; 21}, []); 22 23console.log(data); 24// 0: {data1-num: 1, data1-alpha: "A", data2-num: 4, data2-alpha: "D"} 25// 1: {data1-num: 2, data1-alpha: "B", data2-num: 5, data2-alpha: "E"} 26// 2: {data1-num: 3, data1-alpha: "C", data2-num: 6, data2-alpha: "F"}

投稿2019/07/13 01:26

yasutomi

総合スコア2937

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

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

morohey

2019/07/13 16:58

yasutomi様、ご回答ありがとうございます。 非常に明快なコードに感動しております。reduceについては知らなかったので、大変勉強になりました。ありがとうございました!
guest

0

なんとなくリンク先をみて配列でもできそうだと思ったので形式が違いますが、こういうのを考えました

javascript

1var data1 = [ 2 [1,'A'], 3 [2,'B'], 4 [3,'C'] 5]; 6 7var data2 = [ 8 [4,'D'], 9 [5,'E'], 10 [6,'F'] 11]; 12const zipped = data1.map((e,i)=> e.concat(data2[i])); 13const header = [zipped[0].map((e,i) => `data${(Math.floor(i /2) + 1)}-${(i%2?"alpha":"num")}`)]; 14console.log(header.concat(zipped));

投稿2019/07/12 23:10

papinianus

総合スコア12705

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

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

morohey

2019/07/13 17:01

papinianus様、ご回答ありがとうございます。 形式は違えど、大変参考になりました!感謝いたします。
guest

0

ベストアンサー

js

1var data1 = [ 2 [1,'A'], 3 [2,'B'], 4 [3,'C'] 5]; 6 7var data2 = [ 8 [4,'D'], 9 [5,'E'], 10 [6,'F'] 11]; 12 13var result = [], key, func = ( v, i ) => { 14 if ( !result[ i ] ) result[ i ] = {}; 15 result[ i ][ key + '-num' ] = v[ 0 ]; 16 result[ i ][ key + '-alpha' ] = v[ 1 ]; 17}; 18 19key = 'data1'; 20data1.forEach( func ); 21key = 'data2'; 22data2.forEach( func ); 23 24console.dir( result ); 25```**動くサンプル:**[https://jsfiddle.net/kscu5yhf/](https://jsfiddle.net/kscu5yhf/) 26 27--- 28 29【Array.prototype.forEach() - JavaScript | MDN30[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)

投稿2019/07/12 16:46

kei344

総合スコア69400

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

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

morohey

2019/07/13 16:47

kei344様、回答ありがとうございます。 初心者でもわかりやすく、かつ簡潔なコードに感動致しました。おかげさまで、思い通りのコードを書くことができました。
guest

0

二次元配列

こちらのコードは二次元配列をサポートしているようです。
二次元配列は可搬性が高く、CSV形式とも親和性の高い形式です。

JavaScript

1'use strict'; 2function arraysToArray (...arrayList) { 3 const results = []; 4 5 for (let array of arrayList) { 6 for (let j = 0, len = array.length; j < len; ++j) { 7 const cells = results[j] || (results[j] = []); 8 cells.push(...array[j]); 9 } 10 } 11 12 return results; 13} 14 15var data1 = [ 16 [1,'A'], 17 [2,'B'], 18 [3,'C'] 19]; 20 21var data2 = [ 22 [4,'D'], 23 [5,'E'], 24 [6,'F'] 25]; 26 27data1.unshift(['data1-num','data1-alpha']); 28data2.unshift(['data2-num','data2-alpha']); 29 30const array = arraysToArray(data1, data2); 31 32console.table(array);

ヘッダ行

前コードでは、tableのヘッダ行を unshift で付け足していますが、本来、データと紐づくべき情報なので、予め、dataに入れておくか、別オブジェクトで関連付けを作る仕組みがあると良いと思います。

Re: morohey さん

投稿2019/07/13 08:19

think49

総合スコア18162

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

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

morohey

2019/07/13 17:04

think49様、ご回答ありがとうございます。 リンク先の情報も踏まえた上で、非常にわかりやすく、簡潔なコードを考えてくださり、感激です。ありがとうごさいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問