2009-08-16 17 views
49

Potrzebuję scalić dwie tabele, z treścią drugiej nadpisującej zawartość w pierwszej, jeśli dany element jest w obu. Wyglądałem, ale standardowe biblioteki nie wydają się tego oferować. Gdzie mogę uzyskać taką funkcję?Lua - scalić tabele?

+1

Nie istnieje jeden sposób to zrobić . Czy porównujesz klucze lub wartości w tabeli? Czy jest możliwe, aby klucze/wartości były innymi tabelami? ... –

+0

Nie potrzebuję żadnego porównania, ale będę potrzebował podtabeli ... – RCIX

Odpowiedz

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

czekaj, czy to złapie klucze strunowe i takie? – RCIX

+0

tak, klucze strunowe są obsługiwane –

+0

To powinno działać z pewnymi zmianami w obsłudze podtabeli. Dzięki! – RCIX

16

Oto co wymyśliłem na podstawie odpowiedzi Doug Currie za:

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

Zauważ, że zwykle zły pomysł na bałagan ze standardowymi "przestrzeniami nazw Lua" (jak na przykład tabela. *). Lepiej tworzyć własne. –

+4

"jeśli nie t1 [k] to t1 [k] = {} koniec" zawiera subtelny błąd (znajdź to!) Lepiej zapisz go jako "t1 [k] = t1 [k] lub {}". Co się stanie, jeśli t2 [k] jest tabelą, ale t1 [k] istnieje, ale nie jest tabelą? Wreszcie "table1 [k] = v" powinno być "t1 [k] = v". – lhf

+0

Wszystkie dobre punkty, naprawię je natychmiast. – RCIX

10

nie to będzie działać poprawnie?


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

Tak, ale jeśli spojrzysz na oryginalny post RCIX-a, istniała tam inna logika, która została później uproszczona do dwóch identycznych instrukcji "else". Powinno to zostać jeszcze bardziej uproszczone do tego, co tu masz. – BMitch

+0

Podoba mi się zwięzłość odpowiedzi, dzięki. –

2

Oto iteracyjna wersja do głębokiego scalania, ponieważ nie podoba mi się potencjalne przepełnienie stosu rekursywne.

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

Zapomniałeś sprawdzić, czy 'merge_task' przepełnia twoją dostępną pamięć ... – Irfy

+1

@Irfy, wiesz, że nie możesz tego zrobić w Lua, prawda? –

+1

Mój komentarz został oznaczony jako sarkazm: jeśli unikniesz rekursji, ponieważ boisz się/oczekujesz przepełnienia stosu; a następnie nie sprawdzaj, czy twój kontener zadań przepełnia twoją pamięć, to nie ma większego sensu unikanie rekursji w pierwszej kolejności. – Irfy

1

Odpowiedź Douga Currie jest najprostsza w większości przypadków. Jeśli potrzebujesz bardziej niezawodnego łączenia tabel, rozważ skorzystanie z metody merge() z biblioteki Penlight.

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

-- { 
-- a = 1, 
-- d = 4, 
-- c = 3, 
-- b = 2 
-- } 
+0

Jaki jest trzeci parametr, BTW? –

+0

Trzeci parametr określa sposób łączenia tabel: "true" dla unii, "false" dla przecięcia. https://github.com/stevedonovan/Penlight/blob/master/lua/pl/tablex.lua#L554 – Blackcoat

0

Ja preferowałem wersję Jamesa ze względu na jej prostotę i używam jej w moim utils.lua - dodałem sprawdzanie typu tabeli do obsługi błędów.

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 

Dzięki za ten miły funkcji, które powinny być częścią klasy tabeli tak można nazwać a:merge(b) ale robi table.merge = function(a, b) ... nie działa dla mnie. nawet może być skompresowany do jednej liniowej dla prawdziwych maniaków :)

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

kluczem do rozwiązania strun

3

stołowe numeryczny indeks przejmowanego:

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