Concaténation des tableaux en Lua
ORIGINAL POST
étant Donné qu'il n'existe pas de fonction intégrée en Lua, je suis à la recherche d'une fonction qui me permet d'ajouter des tables. J'ai googlé un peu et avez essayé toutes les solutions que j'ai découvert, mais aucune ne semble fonctionner correctement.
le scénario se passe comme ceci: j'utilise Lua embarqué dans une application. Une commande interne de l'application renvoie une liste de valeurs sous la forme d'un tableau.
ce que j'essaie de faire est d'appeler cette commande de façon récursive dans une boucle et d'ajouter les valeurs retournées, encore une fois sous la forme d'une table, à la table des itérations précédentes.
modifier
pour ceux qui rencontreront ce post dans le futur, veuillez noter ce que @gimf a posté. Comme les Tables de Lua ressemblent autant à des tableaux qu'à n'importe quoi d'autre (même dans un contexte de liste), il n'y a pas de véritable bonne manière d'ajouter une table à l'autre. Le concept le plus proche est la fusion des tables. Veuillez voir le post", " Lua - fusionner les tables? " pour les aider à cet égard.
8 réponses
réponses trop compliquées?
voici mon implémentation:
function TableConcat(t1,t2)
for i=1,#t2 do
t1[#t1+1] = t2[i]
end
return t1
end
pour ajouter deux tableaux ensemble faire ceci
ii=0
for i=#firsttable, #secondtable+#firsttable do
ii=ii+1
firsttable[i]=secondtable[ii]
end
utilisez la première table comme la variable que vous vouliez ajouter car le code ajoute la seconde à la fin de la première table dans l'ordre.
-
i
est le numéro de début du tableau ou de la liste. -
#secondtable+#firsttable
est ce que à la fin.
Il commence à la fin de la première table que vous souhaitez ajouter, et se termine à la fin de la deuxième table dans une boucle for
de sorte qu'elle fonctionne avec n'importe quelle table ou liste de taille.
en général, la notion de concaténation de tables arbitraires n'a pas de sens dans Lua parce qu'une seule clé ne peut avoir qu'une seule valeur.
il y a des cas particuliers où la concaténation a un sens. Un tel est pour les tableaux contenant des tableaux simples, qui pourraient être le résultat naturel d'une fonction destinée à retourner une liste de résultats.
Dans ce cas, vous pouvez écrire:
-- 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
C'est une copie, et ne cherche pas à savoir si une valeur userdata
ou une valeur de fonction est un conteneur ou un objet quelconque qui pourrait nécessiter un traitement différent.
une implémentation alternative pourrait modifier le premier argument plutôt que de créer une nouvelle table. Cela permettrait d'économiser le coût de la copie, et de faire array_concat
différent de l'opérateur ..
sur les chaînes.
Edit: Comme l'a observé dans un commentaire de Joseph Kingry , j'ai omis d'extraire correctement la valeur réelle de chaque argument de ...
. J'ai également échoué à retourner la table fusionnée de la fonction du tout. C'est ce que j'obtiens pour coder dans la boîte de réponse et ne pas tester le code du tout.
une façon simple de faire ce que vous voulez:
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
si vous voulez fusionner deux tables, mais avez besoin d'une copie profonde de la table de résultat, pour quelque raison que ce soit, utilisez la fusion de une autre question sur la fusion des tables plus un code de copie profonde de lua-utilisateurs .
(edit Eh bien, peut-être que vous pouvez modifier votre question pour fournir un exemple minimal... Si vous voulez dire que la table
{ a = 1, b = 2 }
concaténé avec une autre table
{ a = 5, b = 10 }
devrait donner
{ a = 1, b = 2, a = 5, b = 10 }
alors vous n'avez pas de chance. Les touches sont uniques.
Il semble que vous voulez avoir une liste de paires, comme { { a, 1 }, { b, 2 }, { a, 5 }, { b, 10 } }
. Vous pouvez également utiliser une structure finale comme { a = { 1, 5 }, b = { 2, 10 } }
, selon votre application.
mais la simple notion de tables" concaténantes " n'a pas de sens avec les tables Lua. )
Et d'une façon de plus:
for _,v in ipairs(t2) do
table.insert(t1, v)
end
Il me semble plus lisible, elle parcourt la 2ème tableau et ajoute ses valeurs pour le 1er, fin de l'histoire. Curieux comment il se déplace en vitesse à l'indexation explicite [] ci-dessus
Voici une implémentation que j'ai faite similaire à celle de RBerteig ci-dessus, mais en utilisant le paramètre caché arg qui est disponible quand une fonction reçoit un nombre variable d'arguments. Personnellement, je pense que c'est plus lisible par rapport à la syntaxe select.
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
Voici mon implémentation pour concaténer un ensemble de tables d'indexation, FYI.
- définir une fonction pour concaténer deux tableaux,
concat_2tables
-
une autre fonction récursive
concatenateTables
: diviser la liste des tableaux parunpack
, et appelerconcat_2tables
pour concaténertable1
etrestTableList
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)