web-dev-qa-db-ja.com

Luaのテーブルの連結

元の投稿

Luaには組み込み関数がないため、テーブルを一緒に追加できる関数を探しています。私はかなりグーグルし、偶然見つけたすべての解決策を試しましたが、どれも適切に機能していないようです。

シナリオは次のようになります。私は、アプリケーションに埋め込まれたLuaを使用しています。アプリケーションの内部コマンドは、値のリストをテーブルの形式で返します。

私がやろうとしていることは、ループ内でそのコマンドを再帰的に呼び出し、返された値を再びテーブルの形式で、前の反復からのテーブルに追加することです。


[〜#〜]編集[〜#〜]

将来この投稿に遭遇した場合は、@ gimfが投稿した内容に注意してください。 Luaのテーブルは他の何よりも配列に似ているため(リストコンテキストであっても)、あるテーブルを別のテーブルに追加する実際の正しい方法はありません。最も近い概念は、テーブルのマージです。この点については、「 Lua-merge tables? "」の投稿をご覧ください。

27

過度に複雑な答えは?

これが私の実装です:

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

2つのテーブルを一緒に追加するには、これを行います

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

最初のテーブルを、追加したい変数として使用します。コードでは、2番目のテーブルを最初のテーブルの最後に順に追加します。

  • iは、テーブルまたはリストの開始番号です。
  • #secondtable+#firsttableは何で終わるかです。

追加する最初のテーブルの最後から始まり、forループの2番目のテーブルの最後で終わります。これにより、任意のサイズのテーブルまたはリストで機能します。

5
Red_M

一般に、任意のテーブルを連結するという概念はLuaでは意味がありません。単一のキーは1つの値しか持てないためです。

連結が意味をなす特別な場合があります。そのようなものの1つは、単純な配列を含むテーブルの場合です。これは、結果のリストを返すことを目的とした関数の自然な結果である可能性があります。

その場合、次のように書くことができます:

-すべての
-パラメータの連結を含む新しい配列を返します。スケーラーパラメーターが所定の場所に含まれており、配列
-パラメーターの値は最終的な配列に浅くコピーされています。
-ユーザーデータと関数の値はスカラーとして扱われます。
 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 
終わり

これは浅いコピーであり、userdataまたは関数の値が、異なる処理を必要とする可能性のあるコンテナまたはオブジェクトであるかどうかを確認しようとはしません。

別の実装では、新しいテーブルを作成するのではなく、最初の引数を変更する場合があります。これにより、コピーのコストが節約され、array_concatが文字列の..演算子とは異なります。

編集:Joseph Kingry のコメントにあるように、...から各引数の実際の値を適切に抽出できませんでした。また、関数からマージされたテーブルを返すこともできませんでした。これは、解答ボックスでコーディングしてコードをテストしないことで得られるものです。

4
RBerteig

あなたが望むことをする簡単な方法:

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
warspyking

そしてもう一つの方法:

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

それは私にとって最も読みやすいもののようです-2番目のテーブルを反復処理し、その値を最初の1つに追加します。上記の明示的なインデックス付け[]にどの程度の速度で進んでいるのか知りたい

3
Nas Banov

2つのテーブルをマージしたいが、何らかの理由で結果テーブルの詳細なコピーが必要な場合は、 another SOマージテーブルに関する質問 プラス lua-users からコードをディープコピーします。

(editさて、多分あなたは質問を編集して最小限の例を提供することができます...

 { 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テーブルでは意味がありません。

2
gimpf

これは、上記のRBerteigと同様に実行した実装ですが、関数が可変数の引数を受け取ったときに使用できる隠しパラメーターargを使用しています。個人的には、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
1
Neil Sainsbury

純粋な整数のインデックステーブルのセットを連結するための実装は、FYIです。

  1. 2つのテーブルを連結する関数を定義するconcat_2tables
  2. 別の再帰関数concatenateTables:テーブルリストをunpackで分割し、concat_2tablesを呼び出してtable1restTableListを連結します

    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

既存のテーブルを新しいテーブルに連結したい場合は、これが最も簡潔な方法です。

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

これがパフォーマンスに関してどれほど優れているかはわかりませんが。

0
Romário