JavaScript Tips | 配列ユーティリティ:行列転置

JavaScript JavaScript
スポンサーリンク

テーマの整理:「行列転置」とは何か

ここでの「行列転置」は、二次元配列(表データ)で「行と列を入れ替える」ユーティリティのことです。 業務だと、次のような場面で出てきます。

  • Excel で「行と列を入れ替えたい」ときの TRANSPOSE 関数のようなことを、JavaScript でやりたい。
  • 「日付ごとの売上」から「店舗ごとの売上」に、軸を入れ替えたい。
  • ライブラリが「列ごとの配列」を要求しているけれど、手元には「行ごとの配列」しかない。

つまり、「縦と横をひっくり返す」処理を、配列ユーティリティとして持っておくイメージです。

基本コンセプト:二次元配列の「行」と「列」を入れ替える

行列転置のイメージ

まずは、イメージから。

元の配列(行ごと):
[
  [1, 2, 3],  // 行1
  [4, 5, 6],  // 行2
]

転置後の配列(列ごと):
[
  [1, 4],     // 列1
  [2, 5],     // 列2
  [3, 6],     // 列3
]

「行列転置」とは、

  • 元の配列の「行」を「列」に、
  • 元の配列の「列」を「行」に、

入れ替えることです。

Excel でいうと、「縦に並んでいるものを横に並べ直す」「横に並んでいるものを縦に並べ直す」イメージです。

ユーティリティ 1:二次元配列の行列転置 transpose

実装:transpose

まずは、シンプルで分かりやすい転置関数を書きます。

function transpose(matrix) {
  if (!Array.isArray(matrix) || matrix.length === 0) {
    return [];
  }

  const rowCount = matrix.length;
  const colCount = Array.isArray(matrix[0]) ? matrix[0].length : 0;

  if (colCount === 0) {
    return [];
  }

  const result = [];

  for (let col = 0; col < colCount; col++) {
    const newRow = [];
    for (let row = 0; row < rowCount; row++) {
      newRow.push(matrix[row][col]);
    }
    result.push(newRow);
  }

  return result;
}
JavaScript

重要ポイントをかみ砕いて説明

二次元配列かどうか・空かどうかをチェックする matrix が配列でなかったり、要素数が 0 のときは、転置しても意味がないので空配列を返します。

行数と列数を決める rowCount は「行の数」、colCount は「最初の行の列数」です。 ここでは「すべての行が同じ長さ」という前提で考えています(業務で扱う表データはだいたいそうなります)。

外側のループは「列」、内側のループは「行」 転置後の配列では、「元の列」が「新しい行」になります。 だから、外側のループで col を回し、内側のループで row を回しています。

新しい行 newRow に「元の matrix[row][col]」を詰める matrix[row][col] は「元の行 row の、列 col の値」です。 それを「新しい行 newRow」に順番に入れていきます。 こうすることで、「列ごとの配列」ができあがります。

例題 1:シンプルな表データを転置する

コード

const matrix = [
  [1, 2, 3],
  [4, 5, 6],
];

const transposed = transpose(matrix);

console.log(transposed);
JavaScript

出力イメージはこうなります。

[
  [1, 4],
  [2, 5],
  [3, 6],
]
JavaScript

ここでのポイントは、

  • 元の「行 2 行 × 列 3 列」が、
  • 転置後には「行 3 行 × 列 2 列」になっていることです。

「縦と横が入れ替わった」という感覚を、まずここで掴んでください。

例題 2:表データ(ヘッダー付き)を転置する

シナリオ

こんな表データがあるとします。

const table = [
  ["日付", "店舗A", "店舗B"],
  ["2024-07-01", 100, 200],
  ["2024-07-02", 150, 250],
];
JavaScript

これを転置すると、「店舗ごとの日別売上」のような形になります。

コード

const transposedTable = transpose(table);

console.log(transposedTable);
JavaScript

出力イメージはこうなります。

[
  ["日付", "2024-07-01", "2024-07-02"],
  ["店舗A", 100, 150],
  ["店舗B", 200, 250],
]
JavaScript

ここでの重要ポイントは、

  • 元の表では「行ごとに日付+店舗A+店舗B」が並んでいた。
  • 転置後の表では「行ごとに日付の一覧」「店舗Aの一覧」「店舗Bの一覧」が並んでいる。

つまり、「軸を入れ替える」ことで、 “日付を軸にした表”から“店舗を軸にした表”に変わっているわけです。

業務では、「どの軸で見るか」を変えたい場面がよくあるので、 この転置はかなり実用的です。

ユーティリティ 2:不揃いな行長への注意(初心者向けに軽く触れる)

問題になりやすいケース

次のように「行ごとに列数が違う」配列を転置しようとすると、 matrix[row][col]undefined になることがあります。

const badMatrix = [
  [1, 2],
  [3, 4, 5], // 列数が多い
];
JavaScript

この場合、colCount は最初の行の長さ(2)なので、 3 列目の値(5)は転置結果に含まれません。

初心者のうちは、

  • 「行列転置をする配列は、行ごとに列数が同じであること」を前提にする。
  • もし不揃いなデータが来るなら、先に整形してから転置する。

くらいのスタンスで十分です。

ユーティリティ 3:行列転置と他の配列ユーティリティの組み合わせ

組み合わせ例 1:転置してから CSV にする

二次元配列を転置してから CSV にすると、 「縦横を入れ替えた CSV」を簡単に作れます。

function escapeCsvValue(value) {
  if (value === null || value === undefined) return "";
  const str = String(value);
  const needsQuote =
    str.includes(",") || str.includes('"') || str.includes("\n") || str.includes("\r");
  if (!needsQuote) return str;
  const escaped = str.replace(/"/g, '""');
  return `"${escaped}"`;
}

function rowsToCsv(rows) {
  return rows
    .map((row) => row.map((v) => escapeCsvValue(v)).join(","))
    .join("\n");
}

const table = [
  ["日付", "店舗A", "店舗B"],
  ["2024-07-01", 100, 200],
  ["2024-07-02", 150, 250],
];

const transposed = transpose(table);
const csv = rowsToCsv(transposed);

console.log(csv);
JavaScript

ここでのポイントは、

  • 転置によって「見せ方の軸」を変え、
  • その結果を CSV にして外部に渡していることです。

組み合わせ例 2:転置してから「カラム抽出」する

転置後の配列は「列ごとの配列」なので、 特定の列だけを取り出すのも簡単です。

const transposed = transpose(table);

// 例えば「店舗A の行だけ欲しい」
const storeARow = transposed[1]; // ["店舗A", 100, 150]

console.log(storeARow);
JavaScript

「行列転置」を覚えておくと、 他の配列ユーティリティと組み合わせて、 データの見せ方・扱い方を柔軟に変えられるようになります。

行列転置ユーティリティで意識してほしい重要ポイント

「行と列の意味」をちゃんと意識する

行列転置は、単なるテクニックではなく、 「データをどの軸で見るか」を変える操作です。

  • 行が「レコード(1 件分の情報)」なのか、
  • 行が「項目(1 カラムの一覧)」なのか、

を意識しながら転置すると、 「何のために転置しているのか」がはっきりします。

初心者のうちは、

  • まずは「表を 90 度回転させるイメージ」で捉える。
  • 次に「軸を変える」という意味合いを少しずつ理解していく。

くらいで十分です。

「二次元配列の形」をきちんと揃える

転置は、「行数 × 列数」がはっきりしている二次元配列に対して行うのが基本です。 行ごとに列数が違うと、結果が分かりにくくなります。

だからこそ、

  • 転置前に「行ごとの列数が同じか」をざっくり確認する。
  • 必要なら、欠損値を埋めるなどして整形してから転置する。

という意識を持っておくと、 業務データでも安心して使えるようになります。

手を動かして「行列転置」の感覚をつかむ

次のコードを実行して、

  • シンプルな行列の転置
  • 表データの転置

を体感してみてください。

function transpose(matrix) {
  if (!Array.isArray(matrix) || matrix.length === 0) {
    return [];
  }

  const rowCount = matrix.length;
  const colCount = Array.isArray(matrix[0]) ? matrix[0].length : 0;

  if (colCount === 0) {
    return [];
  }

  const result = [];

  for (let col = 0; col < colCount; col++) {
    const newRow = [];
    for (let row = 0; row < rowCount; row++) {
      newRow.push(matrix[row][col]);
    }
    result.push(newRow);
  }

  return result;
}

function demo() {
  const matrix = [
    [1, 2, 3],
    [4, 5, 6],
  ];

  console.log("=== simple transpose ===");
  console.log(transpose(matrix));

  const table = [
    ["日付", "店舗A", "店舗B"],
    ["2024-07-01", 100, 200],
    ["2024-07-02", 150, 250],
  ];

  console.log("=== table transpose ===");
  console.log(transpose(table));
}

demo();
JavaScript

まとめ:行列転置ユーティリティで「配列の縦横を自由に入れ替える」

行列転置は、 「二次元配列の縦と横を入れ替えて、データの見せ方・扱い方を変えるためのユーティリティ」です。

プロジェクトに例えば次のような形で置いておくイメージです。

export function transpose(matrix) { ... }
JavaScript

そして、

  • 表データの軸を変えたいとき
  • Excel 的な「行と列の入れ替え」をしたいとき
  • ライブラリの要求する形に合わせたいとき

には、必ずこの transpose を通す。

こう決めておくと、 配列の世界で「縦横を自由に入れ替える」感覚が身につき、 業務データの扱い方が一段柔軟になります。

行列転置は、数学っぽく聞こえるけれど、 実務では「見方を変えるためのシンプルな道具」です。 その道具を、自分のユーティリティとして持っておくと、かなり心強いですよ。

タイトルとURLをコピーしました