Объединение таблиц в Lua - PullRequest
27 голосов
/ 11 сентября 2009

ОРИГИНАЛЬНЫЙ ПОЧТА

Учитывая, что в Lua нет встроенной функции, я ищу функцию, которая позволяет мне добавлять таблицы вместе. Я немного погуглил и перепробовал все решения, с которыми столкнулся, но ни одно из них не работает должным образом.

Сценарий выглядит следующим образом: я использую Lua, встроенный в приложение. Внутренняя команда приложения возвращает список значений в виде таблицы.

То, что я пытаюсь сделать, это вызвать эту команду рекурсивно в цикле и добавить возвращенные значения, снова в виде таблицы, к таблице из предыдущих итераций.


EDIT

Для тех, кто сталкивается с этим постом в будущем, обратите внимание на то, что опубликовал @gimf. Поскольку таблицы в Lua во многом похожи на массивы, чем на что-либо еще (даже в контексте списка), не существует реального правильного способа добавления одной таблицы к другой. Наиболее близким понятием является объединение таблиц. Пожалуйста, обратитесь к сообщению " Lua - объединить таблицы? " для помощи в этом отношении.

Ответы [ 9 ]

27 голосов
/ 07 марта 2013

Слишком много сложных ответов?

вот моя реализация:

function TableConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    return t1
end
5 голосов
/ 09 апреля 2012

Чтобы сложить две таблицы вместе, сделайте это

    ii=0
for i=#firsttable, #secondtable+#firsttable do
    ii=ii+1
    firsttable[i]=secondtable[ii]
end

используйте первую таблицу в качестве переменной, которую вы хотите добавить, так как код добавляет вторую таблицу в конец первой таблицы по порядку.

  • i - начальный номер таблицы или списка.
  • #secondtable+#firsttable - это то, чем заканчивается.

Он начинается в конце первой таблицы, к которой вы хотите добавить, и заканчивается в конце второй таблицы в цикле for, поэтому он работает с таблицей или списком любого размера.

4 голосов
/ 23 февраля 2015

Простой способ сделать то, что вы хотите:

local t1 = {1, 2, 3, 4, 5}
local t2 = {6, 7, 8, 9, 10}

local t3 = {unpack(t1)}
for I = 1,#t2 do
    t3[#t1+I] = t2[I]
end
4 голосов
/ 12 сентября 2009

В целом понятие объединения произвольных таблиц в Lua не имеет смысла, поскольку один ключ может иметь только одно значение.

Существуют особые случаи, в которых конкатенация имеет смысл. Один из них предназначен для таблиц, содержащих простые массивы, что может быть естественным результатом функции, предназначенной для возврата списка результатов.

В этом случае вы можете написать:

-- return a new array containing the concatenation of all of its 
-- parameters. Scaler parameters are included in place, and array 
-- parameters have their values shallow-copied to the final array.
-- Note that userdata and function values are treated as scalar.
function array_concat(...) 
    local t = {}
    for n = 1,select("#",...) do
        local arg = select(n,...)
        if type(arg)=="table" then
            for _,v in ipairs(arg) do
                t[#t+1] = v
            end
        else
            t[#t+1] = arg
        end
    end
    return t
end

Это мелкая копия, и она не пытается выяснить, является ли userdata или значение функции контейнером или объектом какого-либо вида, который может нуждаться в другой обработке.

Альтернативная реализация может изменить первый аргумент, а не создавать новую таблицу. Это позволило бы сэкономить на копировании и сделать array_concat отличным от оператора .. для строк.

Редактировать: Как заметил в комментарии Джозеф Кингри , мне не удалось должным образом извлечь фактическое значение каждого аргумента из .... Я также не смог вернуть объединенную таблицу из функции вообще. Это то, что я получаю за кодирование в поле ответа, а не за тестирование кода вообще.

2 голосов
/ 21 марта 2015

И еще один способ:

for _,v in ipairs(t2) do 
    table.insert(t1, v)
end

Мне кажется, что он наиболее читаемый - он перебирает 2-ю таблицу и добавляет свои значения к 1-му концу истории. Любопытно, как это происходит в скорости с явной индексацией [] выше

2 голосов
/ 11 сентября 2009

Если вы хотите объединить две таблицы, но по какой-либо причине требуется глубокая копия таблицы результатов, используйте объединение из еще один вопрос SO по объединению таблиц плюс некоторый код глубокой копии из Lua-пользователи .

(* редактировать 1008 * Ну, может быть, вы можете отредактировать свой вопрос, чтобы привести минимальный пример ... Если вы имеете в виду, что таблица

 { a = 1, b = 2 }

объединено с другой таблицей

{ a = 5, b = 10 }

должно привести к

{ a = 1, b = 2, a = 5, b = 10 }

тогда вам не повезло. Ключи уникальны.

Кажется, вы хотите получить список пар, например { { a, 1 }, { b, 2 }, { a, 5 }, { b, 10 } }. Вы также можете использовать конечную структуру, такую ​​как { a = { 1, 5 }, b = { 2, 10 } }, в зависимости от вашего приложения.

Но простое понятие «сцепления» таблиц не имеет смысла для таблиц Lua. )

1 голос
/ 23 октября 2015

Вот моя реализация для объединения набора таблиц с чисто целочисленной индексацией, FYI.

  1. определяет функцию для объединения двух таблиц, concat_2tables
  2. другая рекурсивная функция concatenateTables: разделить список таблиц на unpack и вызвать concat_2tables для объединения table1 и restTableList

    t1 = {1, 2, 3}
    t2 = {4, 5}
    t3 = {6}
    
    concat_2tables = function(table1, table2)
        len = table.getn(table1)
        for key, val in pairs(table2)do
            table1[key+len] = val
        end
        return table1
    end
    
    concatenateTables = function( tableList )
        if tableList==nil then
            return  nil
        elseif table.getn(tableList) == 1 then
            return  tableList[1]
        else
            table1 = tableList[1]
            restTableList = {unpack(tableList, 2)}
            return concat_2tables(table1, concatenateTables(restTableList))
        end
    end
    
    tt = {t1, t2, t3}
    t = concatenateTables(tt)  
    
1 голос
/ 28 ноября 2011

Вот реализация, которую я сделал аналогично описанному выше RBerteig, но используя скрытый параметр arg , который доступен, когда функция получает переменное число аргументов. Лично я думаю, что это более читабельно по сравнению с синтаксисом выбора.

function array_concat(...)
    local t = {}

    for i = 1, arg.n do
        local array = arg[i]
        if (type(array) == "table") then
            for j = 1, #array do
                t[#t+1] = array[j]
            end
        else
            t[#t+1] = array
        end
    end

    return t
end
0 голосов
/ 24 января 2019

Если вы хотите объединить существующую таблицу с новой, это самый краткий способ сделать это:

local t = {3, 4, 5}
local concatenation = {1, 2, table.unpack(t)}

Хотя я не уверен, насколько хорошо это с точки зрения производительности.

...