I am interested in inserting a table within a table in lua
mytable1={"apple","banana","grape"}
mytable2={"one","two","three"}
I want to insert mytable2 in position 4 of mytable1... so after the merger it should look somewhat like this
mytable1={"apple","banana","grape",{"one","two","three"}}
So far I tried it this way:
table.insert(mytable1,4,mytable2)
print(mytable[4])
the result is
table: 0x900b128 instead of mytable2..
I am quite confused.Please advice me where I am doing wrong and what is the right way to proceed.
this is how printing of a table works. Try out print(mytable1) or print(mytable2) and you see a similar output. You used the correct way of inserting that table. Just try out print(table1[4][1]). it should print "one"
Or to get all values try:
for index, value in ipairs(table1[4]) do
print(value);
end
this will print "one", "two" and "three"
Is possible:
tTable = { "apple", "banana", "grape", {"one", "two", "three"}}
tTable[1]
> apple
tTable[4][1]
> one
Print on table does not return it's values, but the indication that's it is a table and it's address.
Source: table inside table in Lua
Suppose you want to simply display everything in your table:
tTable = { "apple", "banana", "grape", {"one", "two", "three"}}
for k,v in pairs(tTable) do
if type(k) == "table" then
for _,i in ipairs(k) do
print(i)
end
else
print(v)
end
end
> apple
> banana
> grape
> one
> two
> three
You've done it correctly; You're just making incorrect assumptions about values, variables and print.
mytable2 is a variable name. You generally won't see variable names as strings except if you are debugging.
A table is a value. No value has a name. table.insert adds a value (or value reference) to a table. In this case, the value is a table so a reference to it is added to the table referenced by the mytable1 variable.
print calls tostring on its arguments. tostring on a table value returns what amounts to a unique identifier. print(mytable2) would print the same string as print(mytable1[4]) because both reference the same table.
Related
Example:
mytable = {{id=100,wordform="One Hundread"},{id=200,wordform="Two Hundread"}}
I want to be able to access the row based on the id to do something like this:
mynum = 100
print ("The value is " .. mytable[mynum].wordform)
The main point here is I want to be able to set the index value so I can predictably retrieve the associated value later as I might do with a java hashmap.
Ideally your table should just use the ID as key:
local mytable = {[100] = {wordform = "One hundred"}, [200] = {wordform = "Two hundred"}}
print("The value is " .. mytable[100].wordform)
If your table is in list form, you can convert it to ID form rather easily:
local mytable_by_id = {}
for _, item in pairs(mytable) do mytable_by_id[item.id] = item end
Using the hash part of a Lua table is definitely preferable over looping over the list entries in linear time as Renshaw's answer suggests (the fact that it's hidden behind a metatable may hide the poor performance and trick the reader into believing a hash indexing operation is taking place here though).
Furthermore, that answer won't even work correctly, as the list part uses integer keys as well; IDs that are valid list part indices would possibly return the wrong element. You'd have to use a function instead of a metatable.
you can use metatable
setmetatable(mytable, {__index = function(tbl, id)
for _, item in pairs(tbl) do
if type(item) == "table" and item.id == id then
return item
end
end
end})
then
mynum = 100
print ("The value is " .. mytable[mynum].wordform) -- The value is One Hundread
So I have this list
numbers = { "one", "two", "three" }
and I'm trying to print it out as
The table "numbers" contains the following entries: one, two, three
what I can't figure out is how to convert the table name to a string to print it out the way I want it to. This is what I've tried so far:
function displayList(name)
listName = tostring(name) -- I've also tried tostring(self)
echo("The contents of \""..listName.."\" are: "..table.concat(name, ", "))
end
and this returns The contents of "table: 0000000000eb9c30" are: one, two, three or The contents of "nil" are: one, two, three if I use tostring(self) instead.
the goal is to be able to print any list I put in the function so I don't want to hard-code "numbers" in there. I would greatly appreciate the help as I feel like I've hit a brick wall with this.
Well in your example, if you refer to the table with a name you could as well just print that name.
So just call something like displayList("numbers", numbers)
For global tables you could do build a lookup table like
local nameLUT = {}
for k,v in pairs(_G) do
nameLUT[v] = k
end
So
numbers = {1,2,3}
print(nameLUT[numbers])
would print "numbers"
A better approach would be to give your table a name via a metamethod.
function nameTable(t, name)
return setmetatable(t, {__tostring = function() return name end})
end
numbers = nameTable({"one", "two", "three"}, "numbers")
print("Table " .. tostring(numbers) .. " contains " .. table.concat(numbers, ", "))
Of course you can use string.format for more advanced formatting or have __tostring even print the contents for you.
I have a key => value table I'd like to sort in Lua. The keys are all integers, but aren't consecutive (and have meaning). Lua's only sort function appears to be table.sort, which treats tables as simple arrays, discarding the original keys and their association with particular items. Instead, I'd essentially like to be able to use PHP's asort() function.
What I have:
items = {
[1004] = "foo",
[1234] = "bar",
[3188] = "baz",
[7007] = "quux",
}
What I want after the sort operation:
items = {
[1234] = "bar",
[3188] = "baz",
[1004] = "foo",
[7007] = "quux",
}
Any ideas?
Edit: Based on answers, I'm going to assume that it's simply an odd quirk of the particular embedded Lua interpreter I'm working with, but in all of my tests, pairs() always returns table items in the order in which they were added to the table. (i.e. the two above declarations would iterate differently).
Unfortunately, because that isn't normal behavior, it looks like I can't get what I need; Lua doesn't have the necessary tools built-in (of course) and the embedded environment is too limited for me to work around it.
Still, thanks for your help, all!
You seem to misunderstand something. What you have here is a associative array. Associative arrays have no explicit order on them, e.g. it's only the internal representation (usually sorted) that orders them.
In short -- in Lua, both of the arrays you posted are the same.
What you would want instead, is such a representation:
items = {
{1004, "foo"},
{1234, "bar"},
{3188, "baz"},
{7007, "quux"},
}
While you can't get them by index now (they are indexed 1, 2, 3, 4, but you can create another index array), you can sort them using table.sort.
A sorting function would be then:
function compare(a,b)
return a[1] < b[1]
end
table.sort(items, compare)
As Komel said, you're dealing with associative arrays, which have no guaranteed ordering.
If you want key ordering based on its associated value while also preserving associative array functionality, you can do something like this:
function getKeysSortedByValue(tbl, sortFunction)
local keys = {}
for key in pairs(tbl) do
table.insert(keys, key)
end
table.sort(keys, function(a, b)
return sortFunction(tbl[a], tbl[b])
end)
return keys
end
items = {
[1004] = "foo",
[1234] = "bar",
[3188] = "baz",
[7007] = "quux",
}
local sortedKeys = getKeysSortedByValue(items, function(a, b) return a < b end)
sortedKeys is {1234,3188,1004,7007}, and you can access your data like so:
for _, key in ipairs(sortedKeys) do
print(key, items[key])
end
result:
1234 bar
3188 baz
1004 foo
7007 quux
hmm, missed the part about not being able to control the iteration. there
But in lua there is usually always a way.
http://lua-users.org/wiki/OrderedAssociativeTable
Thats a start. Now you would need to replace the pairs() that the library uses. That could be a simples as pairs=my_pairs. You could then use the solution in the link above
PHP arrays are different from Lua tables.
A PHP array may have an ordered list of key-value pairs.
A Lua table always contains an unordered set of key-value pairs.
A Lua table acts as an array when a programmer chooses to use integers 1, 2, 3, ... as keys. The language syntax and standard library functions, like table.sort offer special support for tables with consecutive-integer keys.
So, if you want to emulate a PHP array, you'll have to represent it using list of key-value pairs, which is really a table of tables, but it's more helpful to think of it as a list of key-value pairs. Pass a custom "less-than" function to table.sort and you'll be all set.
N.B. Lua allows you to mix consecutive-integer keys with any other kinds of keys in the same table—and the representation is efficient. I use this feature sometimes, usually to tag an array with a few pieces of metadata.
Coming to this a few months later, with the same query. The recommended answer seemed to pinpoint the gap between what was required and how this looks in LUA, but it didn't get me what I was after exactly :- which was a Hash sorted by Key.
The first three functions on this page DID however : http://lua-users.org/wiki/SortedIteration
I did a brief bit of Lua coding a couple of years ago but I'm no longer fluent in it.
When faced with a similar problem, I copied my array to another array with keys and values reversed, then used sort on the new array.
I wasn't aware of a possibility to sort the array using the method Kornel Kisielewicz recommends.
The proposed compare function works but only if the values in the first column are unique.
Here is a bit enhanced compare function to ensure, if the values of a actual column equals, it takes values from next column to evaluate...
With {1234, "baam"} < {1234, "bar"} to be true the items the array containing "baam" will be inserted before the array containing the "bar".
local items = {
{1004, "foo"},
{1234, "bar"},
{1234, "baam"},
{3188, "baz"},
{7007, "quux"},
}
local function compare(a, b)
for inx = 1, #a do
-- print("A " .. inx .. " " .. a[inx])
-- print("B " .. inx .. " " .. b[inx])
if a[inx] == b[inx] and a[inx + 1] < b[inx + 1] then
return true
elseif a[inx] ~= b[inx] and a[inx] < b[inx] == true then
return true
else
return false
end
end
return false
end
table.sort(items,compare)
What is the purpose of Line 2 In my code?
local table = {["First"] = 1, ["Second"] = 2, ["Third"] = 3}
for key, value in pairs(table) do
print(key)
end
Results-------------
First
Second
Third
What is the purpose of the line that says, "for key, value in pairs(table) do
Print(key) ?
I was wondering why it is essential.
As others have suggested in comments, you should really start by reading Programming in Lua. It will explain this and much more and is really a perfect place to start if you want to learn Lua.
Well then, as for what it does
Given a table like this
local tab = {first = 1, second = 2, third = 3}
the way you would usually iterate over all the key-value pairs in the table is like this
for key, value in pairs(tab) do
print(key .. ": " .. tostring(value))
end
This will loop over the three values in the table first = 1, second = 2, etc.
For each pair, key is set to the table key and value to its value. It then executes the code between do and end with those variables set.
So the example above will print the following:
first: 1
second: 2
third: 3
How does it work?
This is a bit more complex; Let's first of all see what pairs actually returns:
> t = {}
> print(pairs(t))
function: 68f18400 table: 0066b1d8 nil
The table it returns as its second argument is the same that we passed in.
The function that's returned by pairs is the next function, which, given a table and a key, returns the next key in the table, within an unknown order but without ever repeating keys.
You can easily confirm that on the command line.
> print(t)
table: 0066b1d8
> print(next)
function: 68f18400
Lua then turns the for loop into something like the following:
do
local f, state, iterator = next, tab, nil -- this is what's returned by pairs
while true do
local key, value = f(state, iterator)
if key == nil then break end
iterator = key
print(key, value) -- This is the body of our for loop
end
end
In Lua, I can add an entry inside table with table.insert(tableName, XYZ). Is there a way I can add already existing table into table? I mean a directly call rather then traversing and add it.
Thanks
The insert in your example will work fine with whatever contents happen to be inside the XYZ variable (number, string, table, function, etc.).
That will not copy the table though it will insert the actual table. If you want to insert a copy of the table then you need to traverse it and insert the contents.
First: In general, you do not need table.insert to put new entries into tables.
A table in Lua is a collection of key-value pairs; entries can be made like this:
local t = {} --the table
local key= "name"
local value = "Charlie"
t[key] = value --make a new entry (replace an existing value at the same key!)
print(t.name) --> "Charlie"
Note that key can have any type (not just integer/string)!
Very often you will need tables for a simple special case of this: A sequence ("list", "array") of values. For Lua, this means you want a table where all the keys are consecutive integers, and contain all non-nil values. The table.insert function is intended for that special case: It allows you to insert a value at a certain position (or to append it at the end of the sequence if no position is specified):
local t = {"a", "b", "d"} --a sequence containing three strings (t[1] = "a", ...)
table.insert(t, "e") --append "e" to the sequence
table.insert(t, 3, "c") --insert "c" at index 3 (moving values at higher indices)
--print the whole sequence
for i=1,#t do
print(t[i])
end
If I understand what you mean correctly, you want to do this:
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
some_function(t1, t2)
-- t1 is now {1, 2, 3, 4, 5, 6}
There is indeed no way to do this without iterating t2. Here is a way to write some_function:
local some_function = function(t1, t2)
local n = #t1
for i=1,#t2 do t1[n+i] = t2[i] end
end
No, you must copy the second table's key/value pairs into the first table. Copying the existing values from the second table is what's known as a "shallow copy." The first table will reference the same objects as the second table.
This works under limited circumstances:
local n = #t1
for i=1,#t2 do t1[n+i] = t2[i] end
It does attempt to shift the t2 elements to just beyond the existing t1 elements. That could be a vital requirement but wasn't stated in the question.
It has a few of problems, though:
By using #t1 and #t2, it misses keys that aren't positive integers and can miss keys that are integers greater than a skipped integer key (i.e. never assigned or assigned nil).
It accesses the first table with an indexer so could invoke the __newindex metamethod. That probably wouldn't be desirable when only copying is wanted.
It accesses the second table with an indexer so could invoke the __index metamethod. That wouldn't be desirable when only copying is wanted.
You might think that ipairs could be used if only positive integer keys are wanted but it quits on the first nil value found so could miss even more than #t2 does.
Use pairs instead:
for key, value in pairs(t2) do
rawset( t1, key, value )
end
If you do want to avoid replacing existing t1 values when the keys match or otherwise map t2 keys in some way then that has to be defined in the requirements.
Bottom line: pairs is the way to get all the keys. It effectively does a rawget so it avoids invoking __index. rawset is the way to do a copy without invoking __newindex.