web-dev-qa-db-ja.com

テーブルからランダムなアイテムを選択してください

私の目標は、Luaのテーブルからランダムなアイテムを選ぶことです。

これは私がこれまでに得たものですが、現在は機能しません:

local myTable = { 'a', 'b', 'c', 'd' }
print( myTable[ math.random( 0, #myTable - 1 ) ] )

上記のコードを修正して意図したとおりに機能させるにはどうすればよいですか? (または、他にどの方法を使用できますか?)

30
Zen

Luaは、Cとは異なり、1からテーブルにインデックスを付けますJavaなど。0から配列にインデックスを付けます。つまり、テーブルでは、有効なインデックスは1、2、3、4です。探しているのは次のとおりです。

_print( myTable[ math.random( #myTable ) ] )
_

引数を1つ指定して呼び出すと、math.random(n)は1からnまでのランダムな整数を返します。

61
Michal Kottman

質問にはもっと一般的な答えも必要だと思います。 1から始まる整数のシーケンスで構築されるluaテーブルに制限はありません。キーは実際には何でもかまいません。他のluaテーブルでもかまいません。このような場合、#myTableのような関数が予期しない答えを返すことがあります(カスタムメタテーブル機能なしで使用した場合)。テーブル内のすべてのキーを取得する唯一の信頼できる方法は、テーブルを反復処理することです。

-- iterate over whole table to get all keys
local keyset = {}
for k in pairs(myTable) do
    table.insert(keyset, k)
end
-- now you can reliably return a random key
random_elem = myTable[keyset[math.random(#keyset)]]

すべてのキーが1から始まる一連の数字である場合、 Michal Kottman による元のソリューションが完全に機能することも追加します。これは、myTable = {'a','b','c'}。したがって、テーブルがこのように構築されている状況では、テーブルからランダムな要素を取得する方が速くなります。

12
ahmadh

テスト:

t = {'a', 'b', 'c'}
print(t[0])

nilを返します。実際、0は範囲外です(t[20]を試してください...)。 table の最初の要素にラベルが付けられているため、randomは1から#myTable(包括的)でなければなりません( expだけを記述した場合は1として、 テーブルコンストラクタ ( "を参照してください。最後に、exp形式のフィールドは[i] =と同等です。 exp、ここでiは1で始まる連続した整数です ")。

math.random に引数nだけを渡すと、1からnまでの乱数が得られます。これはあなたの例を修正します:

print(myTable[math.random(#myTable)])
1
ShinTakezou

私は@ahmadhに触発された次の関数を個人的に使用しています

function random_elem(tb)
    local keys = {}
    for k in pairs(tb) do table.insert(tb, k) end
    return tb[keys[math.random(#keys)]]
end
0
Blincer