見出し画像

【JavaScript】二次元配列(多次元配列)を連想配列に変換する方法


はじめに

こんにちは、SHIFT の IT ソリューション部に所属している Tanaka です。
前回は、一次元配列を二次元配列に変換する方法を記事にしました。
二次元配列は列番号を指定してデータを抽出できたりと一次元配列よりも便利ですが、列番号でしか列の指定ができないという点が不便です。
一方で連想配列は、列名の指定に文字列を使うことができ、より便利です。
そこで今回は、二次元配列を連想配列に変換する方法について、紹介させていただきたいと思います。

二次元配列と連想配列について

まず前提知識として、二次元配列と連想配列について軽く説明します。

配列[ ]の中にもう一階層[ ]が入っている、[ [ ], [ ], [ ] ]のような形の配列のことを二次元配列といい、二次元以上の配列を、まとめて多次元配列といいます。

二次元配列の例(本記事内の個人情報はランダム生成したものであり、実在する人物、組織等とは関係ありません)

[
  ["氏名", "年齢", "性別"],
  ["今野 智博", "75", "男"],
  ["藁谷 玲", "77", "女"],
  ["辻川 ゆきこ", "36", "女"],
  ["宮崎 政利", "45", "男"],
  ["中村 裕加里", "43", "女"],
  ["内山 やよい", "57", "女"],
  ["早川 豊", "47", "男"],
  ["杉山 彩美", "33", "女"],
  ["廣瀬 綾子", "66", "女"],
  ["遠藤 寿彦", "44", "男"],
];

一次元配列よりも整理され、見やすくはなっていますが連想配列であればより見やすく、データを管理・操作するにあたり、扱いやすくなります。

連想配列とはオブジェクト(よって、{ }で囲まれる)の一種で、紐付けされた名前(key)と値(value)の集まりから成るオブジェクトです。{key: value} がセットになっているおかげで、列名の文字列を指定して中身を呼び出すことができるのです。下の例では key に氏名、年齢、性別があり、value に対応する値が入っていることがわかると思います。

連想配列の例

[
  { 氏名: "今野 智博", 年齢: "75", 性別: "男" },
  { 氏名: "藁谷 玲", 年齢: "77", 性別: "女" },
  { 氏名: "辻川 ゆきこ", 年齢: "36", 性別: "女" },
  { 氏名: "宮崎 政利", 年齢: "45", 性別: "男" },
  { 氏名: "中村 裕加里", 年齢: "43", 性別: "女" },
  { 氏名: "内山 やよい", 年齢: "57", 性別: "女" },
  { 氏名: "早川 豊", 年齢: "47", 性別: "男" },
  { 氏名: "杉山 彩美", 年齢: "33", 性別: "女" },
  { 氏名: "廣瀬 綾子", 年齢: "66", 性別: "女" },
  { 氏名: "遠藤 寿彦", 年齢: "44", 性別: "男" },
];

連想配列の便利さ

連想配列がどうして便利か、簡単な例を挙げて説明します。
先ほどの連想配列から、45 歳以上のデータを抽出したいとします。

const data = [
  { 氏名: "今野 智博", 年齢: "75", 性別: "男" },
  { 氏名: "藁谷 玲", 年齢: "77", 性別: "女" },
  { 氏名: "辻川 ゆきこ", 年齢: "36", 性別: "女" },
  { 氏名: "宮崎 政利", 年齢: "45", 性別: "男" },
  { 氏名: "中村 裕加里", 年齢: "43", 性別: "女" },
  { 氏名: "内山 やよい", 年齢: "57", 性別: "女" },
  { 氏名: "早川 豊", 年齢: "47", 性別: "男" },
  { 氏名: "杉山 彩美", 年齢: "33", 性別: "女" },
  { 氏名: "廣瀬 綾子", 年齢: "66", 性別: "女" },
  { 氏名: "遠藤 寿彦", 年齢: "44", 性別: "男" },
];

const over45Age = data.filter((row) => row["年齢"] >= 45); // 45歳よりも上の年齢のデータだけを抽出

console.log(over45Age);

/*
出力結果は
[
  { '氏名': '今野 智博', '年齢': '75', '性別': '男' },
  { '氏名': '藁谷 玲', '年齢': '77', '性別': '女' },
  { '氏名': '宮崎 政利', '年齢': '45', '性別': '男' },
  { '氏名': '内山 やよい', '年齢': '57', '性別': '女' },
  { '氏名': '早川 豊', '年齢': '47', '性別': '男' },
  { '氏名': '廣瀬 綾子', '年齢': '66', '性別': '女' }
]
*/

上の例では、data に代入したデータのうち、45 歳以上のデータだけを Array.prototype.filter()メソッドで抽出し、over45Age という新しい変数に代入しています。なお、今回は簡単化のためアロー関数を用いています。

結果として、45 歳以上のデータが正しく出力されていることがわかります。
列名を指定するだけで、簡単に抽出することができました。

これを二次元配列で行おうとすると、row['年齢']の部分をrow[1]のように、列番号で指定する必要があります(過去の記事を参照)。それでも使えなくはないですが、文字列で指定できた方がデータの列を挿入したときなどに一々番号を変えずに済むので便利です。

ちなみに、filter()メソッドの使い方も過去に記事にしたので、よければ読んでみてくださいね!

二次元配列 → 連想配列への変換コード

先ほどの例の通り、どうせなら連想配列に変換してから処理できれば、とても便利ですよね。
ということで、今回も JavaScript の標準組み込みモジュールで解決しちゃいましょう!

先に、今回の変換コードのフォーマットを置いておきます。皆さん使ってみてくださいね!

const keys = 変換元の変数名[0];
const 変換先の変数名 = 変換元の変数名.slice(1).map((item) => {
  let obj = {};
  keys.forEach((key, i) => (obj[key] = item[i]));
  return obj;
});

使用例

const data = [
  ["氏名", "年齢", "性別"],
  ["今野 智博", "75", "男"],
  ["藁谷 玲", "77", "女"],
  ["辻川 ゆきこ", "36", "女"],
  ["宮崎 政利", "45", "男"],
  ["中村 裕加里", "43", "女"],
  ["内山 やよい", "57", "女"],
  ["早川 豊", "47", "男"],
  ["杉山 彩美", "33", "女"],
  ["廣瀬 綾子", "66", "女"],
  ["遠藤 寿彦", "44", "男"],
];

const keys = data[0];
const newData = data.slice(1).map((item) => {
  let obj = {};
  keys.forEach((key, i) => (obj[key] = item[i]));
  return obj;
});

console.log(newData);

const over45Age = newData.filter((row) => row["年齢"] >= 45); // 45歳よりも上の年齢のデータだけを抽出

console.log(over45Age);

/*
console.log(newData);の出力結果は
[
  { '氏名': '今野 智博', '年齢': '75', '性別': '男' },
  { '氏名': '藁谷 玲', '年齢': '77', '性別': '女' },
  { '氏名': '辻川 ゆきこ', '年齢': '36', '性別': '女' },
  { '氏名': '宮崎 政利', '年齢': '45', '性別': '男' },
  { '氏名': '中村 裕加里', '年齢': '43', '性別': '女' },
  { '氏名': '内山 やよい', '年齢': '57', '性別': '女' },
  { '氏名': '早川 豊', '年齢': '47', '性別': '男' },
  { '氏名': '杉山 彩美', '年齢': '33', '性別': '女' },
  { '氏名': '廣瀬 綾子', '年齢': '66', '性別': '女' },
  { '氏名': '遠藤 寿彦', '年齢': '44', '性別': '男' }
]

console.log(over45Age);の出力結果は
[
  { '氏名': '今野 智博', '年齢': '75', '性別': '男' },
  { '氏名': '藁谷 玲', '年齢': '77', '性別': '女' },
  { '氏名': '宮崎 政利', '年齢': '45', '性別': '男' },
  { '氏名': '内山 やよい', '年齢': '57', '性別': '女' },
  { '氏名': '早川 豊', '年齢': '47', '性別': '男' },
  { '氏名': '廣瀬 綾子', '年齢': '66', '性別': '女' }
]
*/

どうでしょうか、配列を変換し、無事抽出できたと思います。

使用したメソッドの解説

ここでは変換に使ったメソッドの解説をしていきます。

Array.prototype.slice()メソッドは、配列の一部を範囲指定して、新しい配列に返します。元の配列は変更されません。
基本的な構文

配列.slice(開始位置(省略可), 終了位置(省略可))

Array.prototype.map()メソッドは、指定した配列の各要素 1 つずつに対してコールバック関数を実行し、その結果を新しい配列として返すメソッドです。
基本的な構文

配列.map(コールバック関数);

Array.prototype.forEach()メソッドは与えられた関数を、配列の各要素に対して一度ずつ実行するメソッドです。
基本的な構文

配列.forEach(コールバック関数);

実コードの解説

これらを踏まえて変換コードを詳細に解説します。

このコードの目的は、2 次元配列をオブジェクトの配列=連想配列に変換することです。変換の途中で各行のデータがオブジェクトに変換され、最終的にはオブジェクトの配列が生成されます。

1 行目:

const keys = data[0];

この行では、data[0]で 2 次元配列の最初の行(つまり、配列の最初の要素)を指定し、それを変数keysに代入しています。この最初の行は、後でオブジェクトの key として使用します。

2 行目:

const newData = data.slice(1).map(item => {

この行では、まずdata.slice(1)で 2 次元配列の最初の行を除いた部分を新しい配列として取得しています。行は 1 行目を 0 として順番にカウントされるので、slice(1)は配列の 2 行目から最後までを切り出していることになります。
次に、この新しい配列の各要素(各行)に対して.map関数を適用します。今回は、それぞれのitem(行)に対して以下の処理を行う関数が適用されます。

3 行目:

let obj = {};

この行では、空のオブジェクトobjを作成しています。このobjは各行のデータを保存するための一時的な入れ物として機能します。

4 行目:

keys.forEach((key, i) => (obj[key] = item[i]));

この行では、keys配列の各要素(列名)に対して.forEach関数を実行しています。この関数の中では、それぞれのkey(列名)とそれに対応するitem[i](各行の値)を使用して、objオブジェクトに新しいプロパティを追加しています。

5 行目:

return obj;

この行では、新しく作成したobjを返しています。これにより、元の 2 次元配列の各行がオブジェクトに変換され、それらのオブジェクトからなる新しい配列が生成されます。

この一連の処理で 2 次元配列の各行がオブジェクトに変換され、それらのオブジェクトからなる新しい配列が生成されます。この新しい配列はnewDataに代入されます。

おわりに

今回の記事では、二次元配列を連想配列に変換する方法を紹介しました。
この記事が私と同じような JavaScript 初学者の助けになれば幸いです。

もっと知りたい方はこちら


執筆者プロフィール: Atsuhito Tanaka
株式会社SHIFT ITソリューション部所属。現在は、開発支援プロダクト推進部で、テックブーストプロジェクトに参画中。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら

PHOTO:UnsplashMarkus Spiske