Lua中从表格生成所有组合

我正在尝试迭代通过具有可变数量元素的表格,并获取所有可能的组合,仅使用每个元素一次。我得出了以下解决方案。

arr = {"a","b","c","d","e","f"}

function tablelen(table)
  local count = 0
  for _ in pairs(table) do
    count = count + 1
  end
  return count
end

function spellsub(table,start,offset)
  local str = table[start]
  for i = start+offset, (tablelen(table)+1)-(start+offset) do
    str = str..","..table[i+1]
  end
  return str
end

print(spellsub(arr,1,2))    -- 输出: "a,d,e" 正确
print(spellsub(arr,2,2))    -- 输出: "b"     应该是 "b,e,f"

我仍然缺少一些进一步的函数,但我在当前的代码中卡住了。我缺了什么?第一次输出是正确的,但第二次不正确。

点赞
用户2858170
用户2858170

对于像你的具有连续整数键从1开始的表,你可以简单地使用长度运算符。你的tablelen函数是多余的。

table用作本地变量名称会掩盖Lua的表库。我建议您使用tbl或其他不会阻止您使用table方法的名称。

您的代码问题可以通过打印一些调试值来解决:

local arr = {"a","b","c","d","e","f"}

function spellsub(tbl,start,offset)

local str = tbl[start]
print("first str:", str)
  print(string.format("loop from %d to %d", start+offset, #tbl+1-(start+offset)))
  for i = start+offset, (#tbl+1)-(start+offset) do
    print(string.format("tbl[%d]: %s", i+1, tbl[i+1]))
    str = str..","..tbl[i+1]
  end
  return str
end

print(spellsub(arr,1,2))    -- Outputs: "a,d,e" correctly
print(spellsub(arr,2,2))    -- Outputs: "b"     supposed to be "b,e,f"

打印:

first str:  a
loop from 3 to 4
tbl[4]: d
tbl[5]: e
a,d,e
first str:  b
loop from 4 to 3
b

正如您所看到的,由于起始值已经大于限制值,因此第二个循环没有运行。因此,您仅打印第一个值b

我不理解您的代码与您想要实现的内容有何关联,因此我将把修复留给您。

2021-01-18 18:30:39
用户6632736
用户6632736

一个使用递归调用的协程迭代器解决方案:

local wrap, yield = coroutine.wrap, coroutine.yield

-- 这个函数会克隆数组 t 并将 new 添加到其中。
local function append (t, new)
    local clone = {}
    for _, item in ipairs (t) do
        clone [#clone + 1] = item
    end
    clone [#clone + 1] = new
    return clone
end

--[[
    生成 tbl 中非重复项的组合,
    tbl 是项的来源,
    sub 是所有生成的组合都应该包含的项的组合,
    min 是可以添加到生成的组合中的项的最小键。
--]]
local function unique_combinations (tbl, sub, min)
    sub = sub or {}
    min = min or 1
    return wrap (function ()
        if #sub > 0 then
            yield (sub) -- 生成短的组合。
        end
        if #sub < #tbl then
            for i = min, #tbl do    -- 遍历更长的组合。
                for combo in unique_combinations (tbl, append (sub, tbl [i]), i + 1) do
                    yield (combo)
                end
            end
        end
    end)
end

for combo in unique_combinations {'a', 'b', 'c', 'd', 'e', 'f'} do
    print (table.concat (combo, ', '))
end
2021-01-18 19:01:52