如何合并两个表,覆盖两者中的元素?

Posted

技术标签:

【中文标题】如何合并两个表,覆盖两者中的元素?【英文标题】:How to merge two tables overwriting the elements which are in both? 【发布时间】:2010-11-19 23:34:47 【问题描述】:

我需要合并两个表,如果给定项目在两个表中,则第二个表的内容会覆盖第一个表中的内容。我看了,但标准库似乎没有提供这个。我在哪里可以得到这样的功能?

【问题讨论】:

没有单一的方法可以做到这一点。您是在比较表中的键还是值?键/值是否可以是其他表?... 我不需要任何比较,但我需要子表... 【参考方案1】:
for k,v in pairs(second_table) do first_table[k] = v end

【讨论】:

等等,这会捕获字符串键之类的吗? 这应该适用于处理子表的一些调整。谢谢! 如果索引相同,这不会覆盖表中当前的内容,就像在数组中一样?如果您有两个带有数字键 [1]、[2]、[3] 等的表,其中一个已包含数据,您只需遍历第二个表的键,还有 [1]、[2]、[3] 等. 并将具有相同键的相同位置的数据添加到表一,您将覆盖原来存在的任何内容。你可以用 first_table[#first_table + k] = v 解决这个问题。我个人会使用 tables.insert() 来解决这个问题,但不确定 2009 年是否可用! 在 99% 的情况下,这将是正确的解决方案,但请记住,在具有引用其他表的表的应用程序中,这在面向对象模式中很常见,您可能需要这样做额外的簿记。例如,如果出于某种原因,给定的表可能会直接引用自身,则您需要检查v==second_table,如果是,则指定first_table。表也​​可以间接引用自己,但这可能是一本书要解决的问题。我只是想把它放在雷达上,所以'nuff说。 @Astridax 这就是提问者的要求。【参考方案2】:

这是我根据 Doug Currie 的回答得出的结论:

function tableMerge(t1, t2)
    for k,v in pairs(t2) do
        if type(v) == "table" then
            if type(t1[k] or false) == "table" then
                tableMerge(t1[k] or , t2[k] or )
            else
                t1[k] = v
            end
        else
            t1[k] = v
        end
    end
    return t1
end

【讨论】:

请注意,使用标准 Lua“命名空间”(如 table.*)通常是个坏主意。最好自己做。 "if not t1[k] then t1[k] = end" 包含一个微妙的错误(找到它!)最好将其写为 "t1[k] = t1[k] 或 ”。另外,如果 t2[k] 是一个表但 t1[k] 存在但不是一个表,会发生什么?最后,“table1[k] = v”应该是“t1[k] = v”。 tableMerge(t1[k] or , t2[k] or ) 会将 t2 合并到一个新表中,然后丢弃该表。也许应该是t1[k] = tableMerge(t1[k] or , t2[k] or )【参考方案3】:

这不能正常工作吗?


function merge(t1, t2)
    for k, v in pairs(t2) do
        if (type(v) == "table") and (type(t1[k] or false) == "table") then
            merge(t1[k], t2[k])
        else
            t1[k] = v
        end
    end
    return t1
end

【讨论】:

是的,但是如果您查看 RCIX 的原始帖子,其中有一些不同的逻辑,后来被简化为两个相同的 else 语句。它应该被进一步简化成你在这里所拥有的。 谁能解释一下为什么这里需要t1[k] or false【参考方案4】:

对于数字索引表合并:

for k,v in pairs(secondTable) do table.insert(firstTable, v) end

【讨论】:

这个解决方案是不是错了(因为pairs不保证按数字顺序返回元素)?除了table.insert 效率低下,见***.com/a/15278426/5267751(其他答案另见)【参考方案5】:

Doug Currie 的答案在大多数情况下是最简单的。如果您需要更可靠的表合并,请考虑使用 Penlight 库中的 merge() 方法。

require 'pl'
pretty.dump(tablex.merge(a=1,b=2, c=3,d=4, true))

-- 
--   a = 1,
--   d = 4,
--   c = 3,
--   b = 2
-- 

【讨论】:

第三个参数是什么,顺便说一句? 第三个参数决定了表的合并方式:true 用于联合,false 用于交集。 github.com/stevedonovan/Penlight/blob/master/lua/pl/…【参考方案6】:

这是深度合并的迭代版本,因为我不喜欢递归的潜在堆栈溢出。

local merge_task = 
function merge_to_left_o(orig, new)
   merge_task[orig] = new

   local left = orig
   while left ~= nil do
      local right = merge_task[left]
      for new_key, new_val in pairs(right) do
         local old_val = left[new_key]
         if old_val == nil then
            left[new_key] = new_val
         else
            local old_type = type(old_val)
            local new_type = type(new_val)
            if (old_type == "table" and new_type == "table") then
               merge_task[old_val] = new_val
            else
               left[new_key] = new_val
            end
         end
      end
      merge_task[left] = nil
      left = next(merge_task)
   end
end

【讨论】:

我的评论是讽刺:如果你因为害怕/期望堆栈溢出而逃避递归;然后不要检查你的任务容器是否溢出你的内存,那么一开始就逃避递归没有多大意义。 @Irfy,用于 Lua 中的表或其他语言中的类似结构的“通用”内存通常比调用堆栈空间更丰富。当然,应该考虑哪种解决方案适合特定环境,而不是盲目地复制/粘贴一个或另一个。【参考方案7】:

我更喜欢 James 版本,因为它很简单,并在我的 utils.lua 中使用它——我确实添加了检查表类型以进行错误处理。

function merge(a, b)
    if type(a) == 'table' and type(b) == 'table' then
        for k,v in pairs(b) do if type(v)=='table' and type(a[k] or false)=='table' then merge(a[k],v) else a[k]=v end end
    end
    return a
end

感谢这个不错的函数,它应该是 table 类的一部分,所以你可以调用 a:merge(b) 但这样做 table.merge = function(a, b) ... 对我不起作用。对于真正的书呆子,甚至可以压缩成一个衬里:)

【讨论】:

【参考方案8】:

就像Doug Currie说的,你可以使用他的功能,但是他的方法有问题。如果first_tablek 索引中有东西,该函数将覆盖它。

我假设您正在尝试合并这些表,而不是覆盖索引和值。所以这将是我的方法,它非常相似,但用于合并表。

for _, v in pairs(second_table) do table.insert(first_table, v) end

此解决方案的唯一问题是索引设置为数字,而不是字符串。这适用于以数字为索引的表,对于以字符串为索引的表,请使用 Doug Currie 的方法。

Doug Currie 的方法:

for k,v in pairs(second_table) do first_table[k] = v end

【讨论】:

【参考方案9】:
for k,v in pairs(t2) do t1[k] = v end

字符串解决方案的关键

【讨论】:

以上是关于如何合并两个表,覆盖两者中的元素?的主要内容,如果未能解决你的问题,请参考以下文章

合并表而不覆盖mysql phpmyadmin中的现有表

合并两个对象而不覆盖

合并两个数组,并且把相同的数值覆盖掉

在 PowerShell 中合并哈希表:如何?

合并两个数组而不覆盖[重复]

我想用 Python、Pandas、Jupyter 中的另一个主表覆盖一个小表