web-dev-qa-db-fra.com

Concaténation de tables à Lua

ORIGINAL POST

Étant donné qu’il n’existe pas de fonction intégrée dans Lua, je suis à la recherche d’une fonction qui me permette d’ajouter des tableaux. J'ai beaucoup cherché sur Google et j'ai essayé toutes les solutions que j'ai découvertes, mais aucune ne semble fonctionner correctement.

Le scénario est le suivant: j'utilise Lua intégré à une application. Une commande interne de l'application renvoie une liste de valeurs sous la forme d'une table.

Ce que j'essaie de faire, c'est d'appeler cette commande de manière récursive dans une boucle et d'ajouter les valeurs renvoyées, à nouveau sous la forme d'une table, à la table des itérations précédentes.


MODIFIER

Pour ceux qui rencontreront ce message à l’avenir, veuillez noter ce que @gimf a publié. Comme les tableaux de Lua ressemblent autant à des tableaux qu'à toute autre chose (même dans un contexte de liste), il n’existe pas de méthode correcte pour ajouter un tableau à un autre. Le concept le plus proche est la fusion des tables. S'il vous plaît voir le post, " Lua - merge tables? " pour l'aide à cet égard.

27
John Mark Mitchell

Trop de réponses trop?

voici ma mise en oeuvre:

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

Pour ajouter deux tables, faites ceci

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

utilisez la première table car la variable que vous vouliez ajouter en tant que code ajoute la seconde à la fin de la première table dans l'ordre.

  • i est le numéro de départ de la table ou de la liste.
  • #secondtable+#firsttable est ce qu'il faut finir.

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 afin que cela fonctionne avec n'importe quelle table ou liste de tailles.

5
Red_M

En général, la notion de concaténation de tables arbitraires n'a pas de sens en Lua car une clé unique ne peut avoir qu'une seule valeur.

Il existe des cas spéciaux dans lesquels la concaténation a du sens. L'une d'elles concerne les tableaux contenant des tableaux simples, qui pourraient être le résultat naturel d'une fonction destinée à renvoyer une liste de résultats.

Dans ce cas, vous pouvez écrire:

-- renvoie un nouveau tableau contenant la concaténation de tous ses paramètres 
--. Les paramètres du scaler sont inclus à la place, et les valeurs du tableau 
-- sont copiées peu profondes dans le tableau final .
-- Notez que les données utilisateur et les valeurs de fonction sont traitées comme des scalaires .
 Function array_concat (.. .) 
 local t = {} 
 pour n = 1, sélectionnez ("#", ...) do 
 arg local = select (n, ...) 
 si type (arg) == "table" alors 
 pour _, v dans ipairs (arg) do 
 t [# t + 1] = v 
 fin
 autre
 t [# t + 1] = arg 
 fin
 fin
 retourne t 
 end 

Ceci est une copie superficielle et n'essaie en aucun cas de savoir si une valeur userdata ou une fonction est un conteneur ou un objet quelconque nécessitant un traitement différent.

Une autre implémentation pourrait modifier le premier argument plutôt que de créer une nouvelle table. Cela réduirait les coûts de copie et rendrait array_concat différent de l'opérateur .. sur les chaînes.

Modifier: Comme observé dans un commentaire de Joseph Kingry , je n'ai pas réussi à extraire correctement la valeur réelle de chaque argument à partir de .... J'ai également échoué à renvoyer la table fusionnée à partir de la fonction du tout. C'est ce que je reçois pour coder dans la zone de réponse et ne pas tester le code du tout. 

4
RBerteig

Un moyen 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
3
warspyking

Et une autre manière:

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

Cela me semble le plus lisible - il parcourt la deuxième table et ajoute ses valeurs à la première, la fin de l'histoire. Curieux de voir à quel point il se comporte rapidement comme l'indexation explicite [] ci-dessus

2
Nas Banov

Si vous souhaitez fusionner deux tables, mais que vous avez besoin d'une copie complète de la table de résultats, pour une raison quelconque, utilisez la fusion de une autre question SO sur la fusion de tables plus du code de copie complète de lua- utilisateurs .

(edit Eh bien, vous pouvez peut-être modifier votre question pour donner un exemple minimal ... Si vous voulez dire qu'un tableau

 { a = 1, b = 2 }

concaténé avec une autre table

{ a = 5, b = 10 }

devrait aboutir à

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

alors vous n'avez pas de chance. Les clés sont uniques. 

Il semble que vous souhaitiez avoir une liste de paires, telle que { { a, 1 }, { b, 2 }, { a, 5 }, { b, 10 } }. Vous pouvez également utiliser une structure finale telle que { a = { 1, 5 }, b = { 2, 10 } }, selon votre application.

Mais la simple notion de "concaténation" de tableaux n’a aucun sens avec les tableaux de Lua .)

2
gimpf

Voici une implémentation que j'ai faite similaire à celle de RBerteig ci-dessus, mais utilisant le paramètre caché arg qui est disponible lorsqu'une fonction reçoit un nombre variable d'arguments. Personnellement, je pense que ceci est plus lisible que la syntaxe choisie.

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
1
Neil Sainsbury

Voici mon implémentation pour concaténer un ensemble de tables d’indexation d’entiers purs, FYI.

  1. définir une fonction pour concaténer deux tables, concat_2tables
  2. une autre fonction récursive concatenateTables: divise la liste de tables en unpack et appelle concat_2tables pour concaténer table1 et 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
ouxiaogu

Si vous voulez concaténer une table existante dans une nouvelle, c'est la manière la plus concise de le faire:

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

Bien que je ne sois pas sûr de la qualité de cette performance.

0
Romário