You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua嵌套for循环使用table.insert出现重复条目问题求解

问题背景

我目前仍在学习Lua,大概率存在更简便的方式可以实现目标。以下是我从代码中提取的片段,目前90%的功能符合预期,但在最后一步遇到了问题。

inv = {}

for i = 23,mq.TLO.Me.NumBagSlots()+22 do
    inv[i] = {}
    for j = 1,mq.TLO.Me.Inventory(i).Container() do
        inv[i][j]={Item=mq.TLO.Me.Inventory(i).Item(j),bag=i,slot=j}
    end
end

local sortthatsucker={}
for _,bags in pairs(inv) do
    for _,invcontainer in pairs(bags) do
        for _,_ in pairs(invcontainer) do
            local compactstring = tostring(invcontainer.Item).."-"..tostring(invcontainer.bag).."_"..tostring(invcontainer.slot)
            if tostring(invcontainer.Item) ~= "NULL" then
                table.insert(sortthatsucker,compactstring)
            end
        end
    end
end

table.sort(sortthatsucker)
for k,v in pairs(sortthatsucker) do
    print(k,"-",v)
end

当前代码已经可以按需求提取、过滤、排序所有物品,生成包含物品名称和对应“坐标”的复合字符串,得到可按名称排序的简易键值对表;但提取数据时使用的三层嵌套for循环,导致table.insert会在最终表中生成三条完全相同的条目,仅每个条目的键值不同。

示例输出如下:

163-shovel-23_10
164-shovel-23_10
165-shovel-23_10
166-tonsils-18_5
167-tonsils-18_5
168-tonsils-18_5
169-withers-6_12
170-withers-6_12
171-withers-6_12

我的目标是让该表中每个找到的物品仅对应单条条目,后续我会编写新的嵌套循环从字符串中提取背包、槽位坐标值,与对应坐标的物品交互并将其移动到新的坐标位置。如果有方式可以直接创建初始表并直接交互,无需构建嵌套表即可实现同等效果会更好,我经过两周的尝试和搜索仍未找到解决方法。

问题根因

重复条目的来源是多余的第三层for循环:

  • 构建的inv[i][j]本身就是单条物品记录,内部一共只有Item/bag/slot3个键
  • 第三层循环for _,_ in pairs(invcontainer) do会遍历这3个键,相当于每个物品会执行3次插入逻辑,自然会生成3条完全相同的记录
修复方案

最小改动版

直接删除多余的第三层循环即可,不需要改动其他逻辑:

inv = {}

for i = 23,mq.TLO.Me.NumBagSlots()+22 do
    inv[i] = {}
    for j = 1,mq.TLO.Me.Inventory(i).Container() do
        inv[i][j]={Item=mq.TLO.Me.Inventory(i).Item(j),bag=i,slot=j}
    end
end

local sortthatsucker={}
for _,bags in pairs(inv) do
    for _,invcontainer in pairs(bags) do
        local compactstring = tostring(invcontainer.Item).."-"..tostring(invcontainer.bag).."_"..tostring(invcontainer.slot)
        if tostring(invcontainer.Item) ~= "NULL" then
            table.insert(sortthatsucker,compactstring)
        end
    end
end

table.sort(sortthatsucker)
for k,v in pairs(sortthatsucker) do
    print(k,"-",v)
end

优化版(无需构建嵌套中间表)

完全可以跳过inv嵌套表的构建,遍历背包槽位时直接把有效物品加入待排序列表,减少不必要的内存占用:

local sortthatsucker = {}
local bagEnd = 22 + mq.TLO.Me.NumBagSlots()
for bagId = 23, bagEnd do
    local bag = mq.TLO.Me.Inventory(bagId)
    local slotCount = bag.Container()
    for slotId = 1, slotCount do
        local item = bag.Item(slotId)
        if tostring(item) ~= "NULL" then
            table.insert(sortthatsucker, ("%s-%s_%s"):format(tostring(item), bagId, slotId))
        end
    end
end

table.sort(sortthatsucker)
for k,v in pairs(sortthatsucker) do
    print(k,"-",v)
end

如果后续需要直接操作坐标,甚至不用拼接字符串,直接存带itemName/bag/slot字段的表,排序时按物品名排序即可,省掉后续拆分字符串的步骤:

local itemList = {}
local bagEnd = 22 + mq.TLO.Me.NumBagSlots()
for bagId = 23, bagEnd do
    local bag = mq.TLO.Me.Inventory(bagId)
    local slotCount = bag.Container()
    for slotId = 1, slotCount do
        local item = bag.Item(slotId)
        local itemName = tostring(item)
        if itemName ~= "NULL" then
            table.insert(itemList, {
                name = itemName,
                bag = bagId,
                slot = slotId,
                itemObj = item
            })
        end
    end
end

-- 按物品名排序
table.sort(itemList, function(a, b)
    return a.name < b.name
end)

-- 后续直接遍历拿坐标即可,不需要拆分字符串
for idx, itemInfo in ipairs(itemList) do
    print(idx, "-", itemInfo.name, itemInfo.bag, itemInfo.slot)
    -- 直接调用itemInfo.bag、itemInfo.slot即可做物品移动操作
end

内容的提问来源于stack exchange,提问作者KyleB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 22:30:55