0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Lua言語のテーブルをpairsで繰り返すときに出力される順番が変わるのは仕様です。

0
Last updated at Posted at 2026-05-08
a = {foo=10, bar=20, baz=30}
for k, v in pairs(a) do
print(k); print(v)
end

1. Luaのテーブルをpairsで繰り返すときに出力される順番が変わるのは仕様であり、仕様通りの挙動です


解説:pairsの順番が変わる理由

  • Luaのテーブルは「連想配列」として使えますが、キーと値の組み合わせの順序は保証されていません
  • pairs関数は「テーブルの全てのキーと値の組み合わせを順不同で列挙する」関数です
  • つまり、pairsは「順序を気にせず、すべての要素を列挙すること」を目的としていて、
  • 「順番は保証しない」ことが仕様として明確に定められています

仕様上の注意点(高校生向けに重要)

  • 「順番が変わるから、同じ順に処理したい」と思っても、pairsではできません
  • 順序を指定したい場合は、「数値の連続したキー(配列部分)」を使い、ipairsを使う方法があります
  • ただし、ipairsはキーが1から始まる連続した整数のテーブルでのみ順序を保証します
  • キーが文字列(foo, barなど)の場合は順序は未定義です

local a = {foo=10, bar=20, baz=30}
for k, v in pairs(a) do
    print(k, v)
end

これを複数回実行すると、例えば

foo 10
bar 20
baz 30

の順番だったり、

baz 30
foo 10
bar 20

の順番だったりします。


まとめ(重要)

  • pairsの順番は未定義・非保証なので、変わっても正常な動作です
  • 順序を期待したコードは間違いです
  • 順序を制御したい場合は、キーが連番の配列を使いipairsを使いましょう

反例(やってはいけない例)

local a = {foo=10, bar=20, baz=30}
for i = 1, 3 do
    print(a[i]) -- ❌ a[1], a[2], a[3] はnilなので意味なし
end
  • 理由:キーが文字列なので数値キーは存在しない
  • 結果:3回ともnilが出る
  • 「配列のように順序通りにアクセスできる」と思ってはいけません
  • 実行禁止

まとめコメント

-- Luaのpairsは順序を保証しません(仕様)
-- 順序が必要なら連番の配列とipairsを使うこと

2. Luaのテーブルで「順番通りに出力したい」場合は、キーが連続した整数の配列を使い、ipairsで繰り返す方法が正しいです

ポイント

  • 元のテーブルはキーが文字列(foo, bar, baz)なので順序は保証されません
  • 順序を保証したい場合は、「順序を保持したキーのリスト(配列)」を用意する方法が一般的です
  • つまり、順序付けたいキーを配列として別に持ち、順にアクセスします

変更例

元のテーブルと順序を保持する配列を作る例です。

local a = {foo=10, bar=20, baz=30}
local keys = {"foo", "bar", "baz"}  -- 順序を明示的に保持

for i, key in ipairs(keys) do
    print(key, a[key])
end

実行結果(順序保証)

foo 10
bar 20
baz 30

解説

  • keysは配列(1,2,3…の連続整数キー)なので、ipairsで順序通りにアクセス可能です
  • a[key]で元のテーブルの値を取得しています
  • これにより、キーの順序を明示的に管理できます

まとめ

方法 順序保証 対象
pairs(a) なし(仕様) キーが何でもよい
ipairs(a) あり 連続した整数キー(配列)
ipairs(keys) + a[key] あり(明示的管理) 任意のキーを順序付きで扱う

反例(間違った例)

local a = {foo=10, bar=20, baz=30}
for i = 1, 3 do
    print(a[i]) -- ❌ nil nil nil(キーが整数ではないため)
end
  • 理由:a[1], a[2], a[3]は存在しません。
  • 実行禁止です。

もし、テーブルの要素を順序付きで扱いたい場合は、キーを整数にするか、今回のようにキーのリストを別に管理するのがLuaでの安全な方法です。


3.連想配列から、上記のlocal keys = {"foo", "bar", "baz"} を作成するプログラムは作れますか。

連想配列(Luaのテーブル)からキーだけを取り出して配列(連番テーブル)を作るプログラムは作れます。
ただし、Luaのテーブルはキーの順序を持たないため、pairsで取得したキーの順序は不定です
そのため、作成した配列keysの並び順は元の連想配列の「元々の順番」ではなく、任意の順序になります。


連想配列からキーだけを配列にするサンプルコード

local a = {foo=10, bar=20, baz=30}

local keys = {}
for k, _ in pairs(a) do
    table.insert(keys, k)
end

-- keys は {"foo", "bar", "baz"} のような順序だが保証されない

-- 出力確認
for i, key in ipairs(keys) do
    print(i, key)
end

実行例(順序は変わる可能性あり)

1   bar
2   foo
3   baz

順序を固定したい場合

  • Luaの仕様上、元の連想配列の「作成順」や「書き込み順」のキーの順序を自動的に取得することはできません。
  • もし特定の順序が必要なら、あらかじめ順序を示すキーの配列を自分で用意する必要があります

まとめ

項目 ポイント
連想配列のキーを配列化 可能。ただし順序は保証されない(仕様)
元の順序をプログラムで再現する Lua標準仕様ではできない
順序を管理したい場合 別途、順序を示す配列を用意する必要がある

反例:順序を期待して自動生成配列を使う

local a = {foo=10, bar=20, baz=30}
local keys = {}
for k, _ in pairs(a) do
    table.insert(keys, k)
end

for i, key in ipairs(keys) do
    print(key, a[key]) -- ❌ 順序は保証されないため、元の順序と違う可能性あり
end
  • 実行禁止(順序が重要な場合)

4.ipairsを使えば、連想配列でも順番に取り出すことはできますか。

いいえ、ipairsは連想配列(キーが文字列の場合)では順番に取り出せません


理由

  • ipairsは「1から始まる連続した整数キーを持つ配列部分」にのみ使えます。
  • キーが文字列(例:foo, bar, baz)の連想配列には使えず、
  • ipairsでアクセスすると、nilになるか途中で繰り返しが止まります。

例で解説

local a = {foo=10, bar=20, baz=30}

for i, v in ipairs(a) do
    print(i, v)  -- ここは実行されません(a[1]がnilのため)
end

実行結果

何も出力されません。
ipairsは1から連続した整数キーを探しますが、a[1]がnilなので繰り返しは即終了します。


連想配列でipairsを使うと何が起きるか

  • Luaはテーブルの配列部分(整数キーの連続)をipairsで順に返します。
  • 文字列キーは配列部分ではないため無視されます。

連続整数キーの配列でのipairs例(正しい使い方)

local arr = {10, 20, 30}  -- 連続した整数キー1,2,3を持つ配列

for i, v in ipairs(arr) do
    print(i, v)
end

実行結果

1   10
2   20
3   30

まとめ

用途 使う関数 キーの種類 順序保証
連想配列のすべて要素列挙 pairs 文字列など任意 なし(順不同)
配列の順序付き要素列挙 ipairs 1から連続した整数キー あり(連番順)

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?