从Lua中的表中随机选择一个键

时间:2014-03-11 09:20:45

标签: lua lua-table

我想使用可能的项目列表在Lua中随机填充网格,其定义如下:

  -- Items
  items = {}
  items.glass = {}
  items.glass.color = colors.blue
  items.brick = {}
  items.brick.color = colors.red
  items.grass = {}
  items.grass.color = colors.green

所以桌子上的钥匙是“玻璃”,“砖头”和“草”。

如果这些键无法通过数字索引寻址,我如何随机选择其中一个键?

4 个答案:

答案 0 :(得分:1)

嗯,我有一种解决方法,但我会接受任何更好的建议。

第一个解决方案包括一个辅助表,它作为第一个表的索引:

item_index = {"grass", "brick", "glass"}

然后我可以随机存储该表的一个键(board是一个矩阵,用于存储item_index中随机条目的值:

local index = math.random(1,3)
board[i][j] = item_index[index]

之后我可以按如下方式获取原始列表的详细信息:

items[board[y][x]].color

我决定使用的第二个解决方案涉及将已定义的元素作为数组元素添加到原始表中:

  -- Items
  items = {}
  items.glass = {}
  items.glass.color = colors.blue
  table.insert(items, items.glass)   --- Add item as array item
  items.brick = {}
  items.brick.color = colors.red
  table.insert(items, items.brick)   --- Add item as array item
  items.grass = {}
  items.grass.color = colors.green
  table.insert(items, items.grass)   --- Add item as array item

然后,我可以使用索引直接处理元素:

  local index = math.random(1,3)
  board[i][j] = items[index]

可以直接检索它们而无需额外查找:

  board[y][x].color

答案 1 :(得分:0)

虽然你的第二种方法提供了简洁的语法,但我认为第一种方法更容易维护。我无法在这里进行测试,但我认为你可以充分利用这两方面的优势,赢得这项工作:

local items = {
    glass = {
        color = colors.blue,
    },
    brick = {
        color = colors.red,
    },
    grass = {
         color = colors.green,
    },
}
local item_index = {"grass", "brick", "glass"}
local index = math.random(1,3)
board[i][j] = items[item_index[index]]
print('color:', board[i][j].color)

答案 2 :(得分:0)

如果您的桌子不是太大而且您可以随意中断。此方法假定您知道表中的条目数(如果表具有非数字键,则不等于#table值)。

所以找到表的长度,然后在random(1, length(table))处中断,如下:

local items = {} ....
items.grass.color = colors.green

local numitems = 0 -- find the size of the table
for k,v in pairs(items) do
    numitems = numitems + 1
end

local randval = math.random(1, numitems) -- get a random point

local randentry
local count = 0
for k,v in pairs(items) do
    count = count + 1
    if(count == randentry) then
        randentry = {key = k, val = v}
        break
    end
end

货物:您不必跟踪钥匙。它可以是任何表格,您不需要维护它。 坏的和丑陋的:它是O(n) - 两个线性通道。所以,如果你有大桌子,它根本不是理想的。

答案 3 :(得分:0)

以上答案假设你知道所有的密钥是什么,这不是我今天早些时候能够做到的。我的解决方案:

function table.randFrom( t )
    local choice = "F"
    local n = 0
    for i, o in pairs(t) do
        n = n + 1
        if math.random() < (1/n) then
            choice = o      
        end
    end
    return choice 
end

说明:我们不能使用table.getn(t)来获取表的大小,因此我们随时跟踪它。第一项将有1/1 = 1的机会被选中;第二个1/2 = 0.5,依此类推......

如果展开N个项目,则第N个项目将有1 / N的机会被选中。第一项将有1 - (1/2) - (1/3) - (1/4) - ...... - (1 / N)不被替换的机会(记住,它总是首先被选中) 。该系列收敛于1 - (N-1)/ N = 1 / N,等于最后一个项目的选择机会。

因此,数组中的每个项具有相同的被选择的可能性;它是随机的。这也是在O(n)时间运行,这不是很好,但如果你不知道你的索引名称,它是你能做的最好的。