Converting indexed table to keyed table in Lua - lua

I'm a newbie in Lua.
I wonder how to convert indexed table to a key-based table.
For example, Let's say I have the following table.
t = {5, 6, 7, 8}
Now, I understand t[1] is 5, t[2] is 6, t[3] is 7, and t[4] is 8.
What should I do to convert the table t to the following key-based style? (without re-constructing the table again)
t = {x=5, y=6, z=7, w=8}
What would be the most simplest and performant solution to do this?

Try this code:
t = {5, 6, 7, 8}
f = {"x", "y", "z", "w"}
for k=1,#t do
t[f[k]]=t[k]
t[k]=nil
end
for k,v in pairs(t) do
print(k,v)
end

Related

Lua - Find value between 1 - 4 , but only return others

I’m not quite sure how to explain this, but I’m trying to find a way to return all the values between 1 to 4 , that are not the value provided.
For example, let say I provide value ‘2’, I want the process to return 1,3,4 for me to process individually.
To give you a more specific explanation, I’m putting together a script to retrieve the input in use against each output of a 4x4 HDMI matrix. I can retrieve the input in use e.g 2, and enable that button on a UI, but I can’t work out to get the other 3 values, to request that those buttons are turned off on the UI too.
Discover what’s on..(value returned 2)
luup.variable_set("urn:upnp-net:serviceId:Matrix1", "input2", ‘true’,
Turn off the others..
luup.variable_set("urn:upnp-net:serviceId:Matrix1", "input1", ‘false’,
luup.variable_set("urn:upnp-net:serviceId:Matrix1", "input3", ‘false’,
luup.variable_set("urn:upnp-net:serviceId:Matrix1", "input4", ‘false’,
Hope that helps someone to help me ?
function foo(n)
tbl = {1, 2, 3, 4}
table.remove(tbl, n)
return tbl
end
or to also call those functions
function foo(n)
tbl = {1, 2, 3, 4}
luup.variable_set("urn:upnp-net:serviceId:Matrix1", "input"..table.remove(tbl, n), ‘true’)
for num, _ in ipairs(tbl) do
luup.variable_set("urn:upnp-net:serviceId:Matrix1", "input"..num, ‘false’)
end
end

Lua calculating total values in a table in a certain way

local t = {1, 2, 3, 4, 5}
I Need to calculate the total values of t, from the table, the output should be 15. This is a simplified version of a more complex problem and I need to calculate the total values in a certain way, it should look like this:
t = {1, 2, 3, 4, 5}
t = {3, 3, 4, 5} -- the first index is 3, from 1+2 (adding the first and second index value in the table
t = {6, 4, 5} -- the first index is 6, from 3+3
t = {10, 5} -- the first index is 10, from 6+4
t = {15} -- 15 = 10+5
the calculation should stop when there is one value left in the table. How do I code this?
so far I've tried this, no luck
local t = {1,2,3,4,5}
local t2 = {}
--code below runs in a loop, code above doesnt
table.insert(t2, t[1] + t[2])
table.remove(t, 1)
table.remove(t, 1)
for i,v in pairs(t) do
table.insert(t2, v)
end
table.insert(t, t2[1] + t2[2])
table.remove(t2, 1)
table.remove(t2, 1)
for i,v in pairs(t2) do
table.insert(t, v)
end
print(#t) -- total values in t just went higher than before, doesnt work.
Try this code:
local t = {1,2,3,4,5}
while #t>1 do
table.insert(t,1,table.remove(t,1)+table.remove(t,1))
print(t[1],#t)
end
At each step, this code shifts the array twice to the left and once to the right.
Here is a less wasteful solution, which shifts the array only once per step:
local t = {1,2,3,4,5}
while #t>1 do
t[2]=t[1]+t[2]
table.remove(t,1)
print(t[1],#t)
end
Would this work? You keep popping the first value from the table and add the value onto the new first value.
local t = {1, 2, 3, 4, 5}
while (#t > 1) do
local first = t[1];
table.remove(t, 1);
t[1] = t[1] + first;
end
This code modifies the current table each time it loops and does not create a new table.
You are creating tables above the loop. Inside the loop you only pop and add values to existing tables, but for your code to work, you need to generate new tables at each iteration.
Putting print(table.concat(t,', ')) in-between lines of your code will help you to understand what happens. "Correct" one is as follows
local t = {1,2,3,4,5}
local t2
while #t>1 do
t2={}
table.insert(t2, t[1] + t[2])
table.remove(t, 1)
table.remove(t, 1)
for i,v in pairs(t) do
table.insert(t2, v)
end
print('t',table.concat(t,', '))
print('t2',table.concat(t2,', '))
t={}
table.insert(t, t2[1] + t2[2])
table.remove(t2, 1)
table.remove(t2, 1)
for i,v in pairs(t2) do
table.insert(t, v)
end
print('t',table.concat(t,', '))
print('t2',table.concat(t2,', '))
end
print(t[1])
It probably won't matter for small problem, but in general it is a bad style to do array creations and copies in the loop and results in bad performance. (Try replacing t = {1,2,3,4,5} with t={}; for i=1,1e4+1 do t[i]=i; end). Especially if you are not using most elements in the copy most of the time. Also, the above code only works if #t is odd.
Try thinking of alternative ways that don't involve creation of new tables or movements of large tail of array. At least see the guide on queues which are probably more complex trick than that which is needed.

Lua - unpack then pack an array

If I unpack then pack an array:
arr = {1, 2, 3, 4, 5}
arr = table.pack(table.unpack(arr))
Will I guarantee that the resulting arr is the same as the initial arr?
In the documentation it states:
Note that the resulting table may not be a sequence.
What does this mean?
The documentation you cite is talking about nils as in
table.pack(1,nil,3).
Your table is a sequence and so table.unpack(arr) outputs no nils and table.pack(table.unpack(arr)) is a sequence.
However, table.pack(table.unpack(arr)) differs from the original arr because it contains a field n with value 5. This is the only difference.

Lua, seial number replacement

Part of my code is like this:
Load_name:addLoad({'incrementalnodalload', 7, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
the last part (I mean 1,2,...,10) can be extended as much as required (for example 1,2,...,1000).
Thus I want to replace this part with something like this:
Load_name:addLoad({'incrementalnodalload', 7, 1, inc_number})
inc_number = 1:1000
However, it does not work!
Any suggestion is highly appreciated!
Here is inc_number function that accepts two parameters and does what you need in this context:
function inc_number(f,t)
if f > t then return else return f,inc_number(f+1,t) end
end
Load_name:addLoad({'incrementalnodalload', 7, 1, inc_number(1,100)})
Note that it only works when the result of inc_number call is the last parameter in the list of parameters. Example:
print(table.concat({inc_number(1,10)}, ","))
-- prints: 1,2,3,4,5,6,7,8,9,10

Why does this array slice return an empty array instead of nil? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Array slicing in Ruby: looking for explanation for illogical behaviour (taken from Rubykoans.com)
I've been playing around with array slicing in ruby but I don't understand the last 2 results below:
a = [1,2,3]
a[2,1] # output is [3]
a[3,1] # output is [] ...why??
a[4,1] # output is nil ...according to the docs this makes sense
Why would a[3,1] be an empty array while a[4,1] is nil?
If anything, I would expect a[3,1] to return nil as well. According to the ruby docs an array split should return nil if the start index is out of range. So why is it that a[3,1] is not returning nil?
Note: This is on ruby 1.9.2
You're asking for the end of the array, which is []. Look at it this way: the Array [1,2,3] can be considered to be constructed from cons cells as such: (1, (2, (3, ())), or 1:2:3:[]. The 3rd index (4th item) is then clearly [].
" Returns nil if the index (or starting index) are out of range."
a[3,1] is a special case according to the example in the same link.
more info can be seen here by the way: Array slicing in Ruby: looking for explanation for illogical behaviour (taken from Rubykoans.com)
It's easier to understand why if you imagine the slice on the left side of an assignment.
>> (b = a.clone)[2,1] = :a; p b
[1, 2, :a]
>> (b = a.clone)[2,0] = :b; p b
[1, 2, :b, 3]
>> (b = a.clone)[3,1] = :c; p b
[1, 2, 3, :c]
>> (b = a.clone)[3,0] = :d; p b
[1, 2, 3, :d]

Resources