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

从Lua中的表中随机选择一个键,lua,lua-table,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 items[board[y][x]].color 所以桌子的钥匙是

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

  -- Items
  items = {}
  items.glass = {}
  items.glass.color = colors.blue
  items.brick = {}
  items.brick.color = colors.red
  items.grass = {}
  items.grass.color = colors.green
items[board[y][x]].color
所以桌子的钥匙是玻璃、砖和草


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

嗯,我有一个解决办法,但我愿意接受任何更好的建议

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

item_index = {"grass", "brick", "glass"}
然后我可以随机存储该表的一个键。该表是一个矩阵,用于存储项_索引中随机项的值:

之后,我可以获得原始列表的详细信息,如下所示:

  -- Items
  items = {}
  items.glass = {}
  items.glass.color = colors.blue
  items.brick = {}
  items.brick.color = colors.red
  items.grass = {}
  items.grass.color = colors.green
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

虽然您的第二个方法提供了简洁的语法,但我认为第一个方法更易于维护。我不能在这里测试,但我认为你可以两者兼得,这行得通吗:

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)

若你们的桌子不是太大,你们可以随意在一个点上停下来。如果表中有非数字键,则此方法假定您知道表中不等于表值的条目数

找到表格的长度,然后在random1,lengthtable处断开,如下所示:

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
货物:你不必跟踪钥匙。它可以是任何表,您不需要维护它。
坏的和丑陋的:它是两次线性传递。因此,如果你有一张大桌子,它一点也不理想。

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

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,这等于最后一项被选中的概率


因此,数组中的每个项目被选择的可能性相等;它是一致随机的。这也会按时运行,虽然不是很好,但如果不知道索引名,这是最好的方法。

该方法称为哈希表查找。不,我不认为在这种情况下可以使用其他方法。谢谢你的确认。不管怎么说,这也不算太糟,只是多了一点肘部润滑脂。理论上,如果有意义的话,我可以使用相同的表并将键控项添加为数组项。