多次元配列(配列の配列)
『Zig』では、多次元配列は「配列の配列」として表現します。2次元配列の型は [行数][列数]T の形式で宣言し、要素へのアクセスは arr[行][列] のように複数のインデックスを連ねます。コンパイル時にサイズが確定するため、スタック上に効率よく確保されます。ここでは、2次元・3次元配列の宣言・初期化・要素アクセスの方法を解説します。
構文
// -----------------------------------------------
// 2次元配列の宣言と初期化
// -----------------------------------------------
// [行数][列数]T 型で宣言します
// 外側の添字が行、内側の添字が列に対応します
const matrix: [行数][列数]T = [行数][列数]T{
[列数]T{ 値, 値, ... }, // 行 0
[列数]T{ 値, 値, ... }, // 行 1
};
// [_][列数]T と書くと行数をコンパイラが推論します
// ※ 内側の列数は省略できません
const matrix = [_][列数]T{
[_]T{ 値, 値, ... },
[_]T{ 値, 値, ... },
};
// -----------------------------------------------
// 要素へのアクセス
// -----------------------------------------------
matrix[行インデックス][列インデックス] // 要素を取得します
matrix[行インデックス][列インデックス] = 値; // var 宣言の場合のみ代入できます
// -----------------------------------------------
// 次元ごとの長さ取得
// -----------------------------------------------
matrix.len // 行数(外側の配列の要素数)を返します
matrix[0].len // 列数(内側の配列の要素数)を返します
// -----------------------------------------------
// ゼロ初期化(2次元)
// -----------------------------------------------
var matrix = [_][列数]T{[_]T{0} ** 列数} ** 行数;
構文一覧
| 構文/メソッド | 概要 |
|---|---|
[行数][列数]T{ ... } | 行数×列数の2次元固定長配列リテラルを定義します。 |
[_][列数]T{ ... } | 行数をリテラルから推論して2次元配列を定義します。内側の列数は省略できません。 |
arr[i][j] | 行インデックス i、列インデックス j の要素を取得します。どちらも 0 始まりです。 |
arr[i][j] = 値 | var 宣言の2次元配列の要素に値を代入します。 |
arr.len | 外側配列の要素数(行数)を usize 型で返します。 |
arr[0].len | 内側配列の要素数(列数)を usize 型で返します。 |
[_]T{0} ** N | 値 0 を N 個並べた1次元配列を生成します。2次元のゼロ初期化に組み合わせて使います。 |
for (arr) |row| { for (row) |val| } | ネストした for ループで2次元配列の全要素を走査します。 |
サンプルコード
kof_multi_array.zig
// kof_multi_array.zig — 多次元配列の宣言・アクセス・走査のサンプルです
// KOF(ザ・キング・オブ・ファイターズ)のキャラクターを使って
// 2次元配列・配列の配列の基本操作を確認します
// 標準ライブラリをインポートします
const std = @import("std");
pub fn main() !void {
// 標準出力への Writer を取得します
const stdout = std.io.getStdOut().writer();
// -----------------------------------------------
// 1. 文字列の2次元配列(チームごとのメンバー一覧)
// -----------------------------------------------
// [チーム数][メンバー数][]const u8 の形で宣言します
// 各チームは 3 名で構成されます
const teams = [_][3][]const u8{
// ヒーローズチーム
[_][]const u8{ "テリー・ボガード", "草薙京", "八神庵" },
// ファタルフューリーチーム(ゲスト入り)
[_][]const u8{ "不知火舞", "ラルフ・ジョーンズ", "テリー・ボガード" },
};
try stdout.print("=== KOF チームロスター ===\n\n", .{});
// teams.len で外側(チーム数)の長さを取得します
try stdout.print("チーム数: {d}\n", .{teams.len});
// teams[0].len で内側(メンバー数)の長さを取得します
try stdout.print("1チームあたりの人数: {d}\n\n", .{teams[0].len});
// ネストした for でチーム→メンバーの順に走査します
for (teams, 0..) |team, team_idx| {
try stdout.print("--- チーム {d} ---\n", .{team_idx + 1});
for (team, 0..) |fighter, pos| {
// [行][列] のインデックスに対応します
try stdout.print(" [{d}][{d}] {s}\n", .{ team_idx, pos, fighter });
}
try stdout.print("\n", .{});
}
// -----------------------------------------------
// 2. 数値の2次元配列(技のパワーゲージ消費量)
// -----------------------------------------------
// var 宣言にすることで要素を書き換えられます
// [ファイター数][技の種類数]u16 の2次元配列を定義します
// 列 0: 必殺技、列 1: スーパー必殺技、列 2: MAX 超必殺技
var power_cost = [_][3]u16{
[_]u16{ 0, 1, 3 }, // テリー・ボガード
[_]u16{ 0, 1, 3 }, // 草薙京
[_]u16{ 0, 1, 3 }, // 八神庵
[_]u16{ 0, 1, 2 }, // 不知火舞(MAX コスト低め)
[_]u16{ 0, 1, 3 }, // ラルフ・ジョーンズ
};
// 特定要素を書き換えます(var 宣言なので変更可能です)
// ラルフの MAX 超必殺技のコストを 3 に更新します
power_cost[4][2] = 3;
const fighter_names = [_][]const u8{
"テリー・ボガード",
"草薙京",
"八神庵",
"不知火舞",
"ラルフ・ジョーンズ",
};
const skill_names = [_][]const u8{
"必殺技 ",
"スーパー必殺技",
"MAX超必殺技 ",
};
try stdout.print("--- パワーゲージ消費量 ---\n", .{});
try stdout.print("ファイター ", .{});
for (skill_names) |skill| {
try stdout.print("{s} ", .{skill});
}
try stdout.print("\n", .{});
// 外側のループで行(ファイター)を走査します
for (fighter_names, power_cost) |name, costs| {
try stdout.print("{s} ", .{name});
// 内側のループで列(技の種類)を走査します
for (costs) |cost| {
try stdout.print("{d} ", .{cost});
}
try stdout.print("\n", .{});
}
try stdout.print("\n", .{});
// -----------------------------------------------
// 3. 直接インデックスアクセス
// -----------------------------------------------
// [行][列] の形式で特定の要素を取得します
try stdout.print("--- 直接アクセスの例 ---\n", .{});
try stdout.print(
"{s} の MAX超必殺技コスト: {d}\n",
.{ fighter_names[2], power_cost[2][2] },
);
try stdout.print(
"{s} のスーパー必殺技コスト: {d}\n",
.{ fighter_names[3], power_cost[3][1] },
);
}
zig run kof_multi_array.zig === KOF チームロスター === チーム数: 2 1チームあたりの人数: 3 --- チーム 1 --- [0][0] テリー・ボガード [0][1] 草薙京 [0][2] 八神庵 --- チーム 2 --- [1][0] 不知火舞 [1][1] ラルフ・ジョーンズ [1][2] テリー・ボガード --- パワーゲージ消費量 --- ファイター 必殺技 スーパー必殺技 MAX超必殺技 テリー・ボガード 0 1 3 草薙京 0 1 3 八神庵 0 1 3 不知火舞 0 1 2 ラルフ・ジョーンズ 0 1 3 --- 直接アクセスの例 --- 八神庵 の MAX超必殺技コスト: 3 不知火舞 のスーパー必殺技コスト: 1
概要
『Zig』の多次元配列は「配列の配列」で表現します。2次元配列の型は [行数][列数]T と書き、要素へのアクセスは arr[i][j] の形式を使います。行数は [_] でコンパイラに推論させることができますが、内側(列数)は必ず明示する必要があります。全要素を走査するにはネストした for ループを使い、外側で行、内側で列を順に処理します。要素数の取得は外側の長さが arr.len、内側の長さが arr[0].len です。var 宣言であれば arr[i][j] = 値 で任意の要素を書き換えられます。ゼロ初期化には [_]T{0} ** 列数 を行数分繰り返す書き方が便利です。1次元配列の基本については 配列の基本 を、動的に伸縮する配列が必要な場合は ArrayList(動的配列) を合わせて確認してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。