2009-08-16 4 views
49

2つのテーブルをマージする必要があります.2つ目のテーブルの内容を上書きする必要があります。私は見ましたが、標準ライブラリはこれを提供していないようです。どこでそのような機能を得ることができますか?Lua - テーブルをマージしますか?

+1

これを行うための単一の方法はありません。あなたはテーブルのキーや値を比較していますか?キー/値が別のテーブルになる可能性はありますか?... –

+0

私は比較をする必要はありませんが、サブテーブルが必要になります... – RCIX

答えて

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

待ち、文字列キーなどをキャッチしますか? – RCIX

+0

はい、文字列キーが処理されます –

+0

これは、サブテーブルを処理するための調整が必要です。ありがとう! – RCIX

16

は、ここで私はダグ・クリーの回答に基づいて思い付いたものです:

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 
+6

標準的なLuaの "namespace"(表。*など)を混乱させるのは悪い考えです。あなた自身のものを作ることをお勧めします。 –

+4

"t1 [k] = t1 [k] = {} end"に微妙なバグがあります(見つけてください) "t1 [k] = t1 [k]または{}"と書いてください。 また、t2 [k]がテーブルで、t1 [k]は存在しますがテーブルではない場合はどうなりますか? 最後に、 "table1 [k] = v"は "t1 [k] = v"でなければなりません。 – lhf

+0

良い点、すぐに修正します。 – RCIX

10

が正しく、この作品ではないでしょうか?


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 
+2

はい、RCIXの元の投稿を見ると、いくつかの異なるロジックがあり、後で2つの同じ 'else'ステートメントに単純化されました。あなたがここにいるものにさらに単純化されているはずです。 – BMitch

+0

私はあなたの答えの簡潔さが好きです、ありがとう。 –

2

ここでは、再帰的なスタックオーバーフローの可能性が低いため、深いマージのための反復バージョンです。

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 
+0

'merge_task'が利用可能なメモリをオーバーフローしているかどうかをチェックするのを忘れました... – Irfy

+1

@Irfy、あなたはLuaでそれを行うことはできませんよね? –

+1

私のコメントは皮肉のものでした:あなたが恐怖/スタックのオーバーフローが予想されるので、再帰をエスケープする場合。あなたのタスクコンテナがあなたのメモリをオーバーフローしているかどうかをチェックしないと、最初は再帰を逃れることはあまり意味がありません。 – Irfy

1

ダグ・カリーの答えは、ほとんどの場合最も簡単です。より堅牢なテーブルのマージが必要な場合は、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 
-- } 
+0

3番目のパラメータBTWとは何ですか? –

+0

3番目のパラメータは、表がどのようにマージされるかを決定します。共用体の場合は「true」、交差部の場合は「false」です。 https://github.com/stevedonovan/Penlight/blob/master/lua/pl/tablex.lua#L554 – Blackcoat

0

シンプルでわかりやすく、私のutils.luaで使用することをお勧めしました。エラー処理のためにテーブルタイプのチェックを追加しました。あなたがa:merge(b)を呼び出すことができますがtable.merge = function(a, b) ...を行うことは私のために動作しませんでしたので、テーブルクラスの一部である必要があり、この素敵な機能のための

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 

感謝。でも数値インデックステーブルのマージの文字列ソリューション

0
for k,v in pairs(t2) do t1[k] = v end 

キーの1つのライナーに圧縮することができる:

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

のために本物のオタク:)

関連する問題