Подтвердить что ты не робот

Конкатенация таблиц в Lua

ОРИГИНАЛЬНАЯ ПОЧТА

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

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

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


ИЗМЕНИТЬ

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

4b9b3361

Ответ 1

Сложные ответы много?

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

function TableConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    return t1
end

Ответ 2

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

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

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

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

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

Ответ 3

В общем, понятие конкатенирования произвольных таблиц не имеет смысла в 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 отличным от оператора .. в строках.

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

Ответ 4

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

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

Ответ 5

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

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

 { 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. )

Ответ 6

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

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

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

Ответ 7

Вот реализация, которую я сделал аналогично 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

Ответ 8

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

  • определить функцию для объединения двух таблиц, concat_2tables
  • другая рекурсивная функция 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)  
    

Ответ 9

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

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

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