views:

1119

answers:

2

ORIGINAL POST

Given that there is no built in function in Lua, I am in search of a function that allows me to append tables together. I have googled quite a bit and have tried every solutions I stumbled across but none seem to work properly.

The scenario goes like this: I am using Lua embeded in an application. An internal command of the application returns a list of values in the form of a table.

What I am trying to do is call that command recursively in a loop and append the returned values, again in the form of a table, to the table from previous iterations.

Thank you in advanced for your help.


EDIT

For those who come across this post in the future, please note what gimf posted. Since Tables in Lua are as much like arrays than anything else (even in a list context), there is no real correct way to append one table to another. The closest concept is merging of tables. Please see the post, "Lua - merge tables?" for help in that regard.

+1  A: 

If you want to merge two tables, but need a deep copy of the result table, for whatever reason, use the merge from another SO question on merging tables plus some deep copy code from lua-users.

(edit Well, maybe you can edit your question to provide a minimal example... If you mean that a table

 { a = 1, b = 2 }

concatenated with another table

{ a = 5, b = 10 }

should result in

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

then you're out of luck. Keys are unique.

It seems you want to have a list of pairs, like { { a, 1 }, { b, 2 }, { a, 5 }, { b, 10 } }. You could also use a final structure like { a = { 1, 5 }, b = { 2, 10 } }, depending on your application.

But the simple of notion of "concatenating" tables does not make sense with Lua tables. )

gimpf
gimf, you were right. I was misinterpreting the use of lists in Tables to think that they could simply be concatenated. Further testing led me to the conclusion that what I really needed to be doing was a merge. Thank you for your help and patience with a Lua newbie.
John Mark Mitchell
@John, we were all newbies once... coming from complex languages, it is sometimes surprising how much power is hiding inside Lua's simplicity. It can take a while to grok it.
RBerteig
+2  A: 

In general the notion of concatenating arbitrary tables does not make sense in Lua because a single key can only have one value.

There are special cases in which concatenation does make sense. One such is for tables containing simple arrays, which might be the natural result of a function intended to return a list of results.

In that case, you can write:

-- 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

This is a shallow copy, and makes no attempt to find out if a userdata or function value is a container or object of some kind that might need different treatment.

An alternative implementation might modify the first argument rather than creating a new table. This would save the cost of copying, and make array_concat different from the .. operator on strings.

Edit: As observed in a comment by Joseph Kingry, I failed to properly extract the actual value of each argument from .... I also failed to return the merged table from the function at all. That's what I get for coding in the answer box and not testing the code at all.

RBerteig
+1 on the notion for "natural result of a function ... return a list of results". This is quite probable.
gimpf
I think there is an error in this function, I think you need another `select` in there after the `for` to get the actual value out of `...`. http://lua-users.org/wiki/VarargTheSecondClassCitizen See Issue 8
Joseph Kingry
Yup. Apparently I didn't test this code before posting, or that defect would have been obvious. More obvious in hindsight is the missing `return t` before the last `end`.
RBerteig