LoginSignup
0
1

More than 3 years have passed since last update.

[JavaScript] ヘッダ行のある2次元配列をMapの配列に変換

Last updated at Posted at 2021-01-15

目的

GAS(Google Apps Script)でGoogleスプレッドシートのデータをsheet.getDataRange().getValues()で2次元配列として取り出し後、加工してsetValues()で書き戻す、というのはよくあると思う。

2次元配列のままでは列の追加や削除、入れ替えなどの変更に対して弱いのでこれまではObjectに変換してから処理していたのだが、Objectではキー(プロパティ)の順序が保証されない(=スプレッドシートに書き戻したときに列の順序が変わってしまう可能性がある)、ということを知ったので、順序が保証されるMapに変換することに。

ということで、1行目がヘッダである2次元配列と、Mapの配列を相互に変換する関数を作成した(V8エンジン限定)。

できたもの

/**
 * 2次元配列(第1行はヘッダ)をMapの配列に変換
 * @param {Array<Array>} table 第1行をヘッダとする2次元配列
 * @return {Array<Map>} Mapの配列
 */
function tableToMaps(table){
  const headers = table[0];
  return table.slice(1).map((e) => e.reduce((i,n,a) => i.set(headers[a], n), new Map()));
}

/**
 * Mapの配列を2次元配列(第1行はヘッダ)に変換
 * @param {Array<Map>} maps Mapsの配列
 * @return {Array<Array>} 第1行をヘッダとする2次元配列
 */
function mapsToTable(maps){
  const headers = [...maps[0].keys()];
  return [headers, ...maps.map((e) => (headers.map((h) => e.get(h))))]
}

エラー処理等はしてないので適当に呼び出し側で😁

2次元配列 → Mapの配列

const table = [
  ["col1", "col2", "col3", "col4"],
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  ["a", "b", "c", "d"]
];
const maps = tableToMaps(table);

image.png

Mapの配列 → 2次元配列

mapsToTable(maps);

image.png

補足

オブジェクトの配列との変換

ちなみにそれまで使っていたObjectの配列と2次元配列との相互変換は以下。

/**
 * 2次元配列(第1行はヘッダ)をオブジェクトの配列に変換
 * @param {Array<Array>} table 第1行をヘッダとする2次元配列
 * @return {Array<Object>} オブジェクトの配列
 */
function tableToObjects(table){
  const headers = table[0];
  return table.slice(1).map((e) => e.reduce((i,n,a) => {i[headers[a]] = n; return i;}, {}));
}

/**
 * オブジェクトの配列を2次元配列(第1行はヘッダ)に変換
 * @param {Array<Object>} objects オブジェクトの配列
 * @return {Array<Array>} 第1行をヘッダとする2次元配列
 */
function objectsToTable(objects){
  const headers = Object.keys(objects[0]);
  return [headers, ...objects.map((e) => (headers.map((h) => e[h])))];
}

ちなみに{i[headers[a]] = n; return i;}({...i, [headers[a]]: n})と書いたら速度が1/3程度まで落ちた。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1