Looping an array of tables - lua

How can I loop this array of tables?
TASK_CONFIG = {
[1] = {NAME = "1-a", COUNT = 10, REWARD = 1000},
[2] = {NAME = "4-b", COUNT = 10, REWARD = 6000},
[3] = {NAME = "3-a", COUNT = 15, REWARD = 2400},
}
I need something like:
for each ITEM in TASK_CONFIG
for each FIELD in ITEM
-- do something
next
next
The idea is looping every field, for example:
Looping every row and getting the values "name", "count", "reward"

for a, b in pairs(TASK_CONFIG) do
for c, d in pairs(b) do
-- print info / do something
end
end

Related

LUA - Most common item in the table

I have a table like below, I don't need to know which product sells how much, I just want to know which product is the most popular. Do you have any idea which method is the best way to do this?
Like in the example below, knowing that because 3 of the product "blue" have been sold, it is the most popular
local products = {}
products["430373bb5b7a40a04f9"] = "red"
products["0dce4263af4b5cfe0de"] = "red"
products["cf2559afb736c1eb1bc"] = "green"
products["abc4d248541c3386c88"] = "blue"
products["bb9386c65270948ebee"] = "blue"
products["b193fba741cd646a9c0"] = "blue"
this example will count the number of sales in a single pass.
local products = {}
products["430373bb5b7a40a04f9"] = "red"
products["0dce4263af4b5cfe0de"] = "red"
products["cf2559afb736c1eb1bc"] = "green"
products["abc4d248541c3386c88"] = "blue"
products["bb9386c65270948ebee"] = "blue"
products["b193fba741cd646a9c0"] = "blue"
local pop = {}
for k,v in pairs(products) do
pop[v] = (pop[v] or 0) + 1
end
-- if you need to sort by sales then:
local pop_s = {}
for k,v in pairs(pop) do
pop_s[#pop_s+1] = { item=k, sales=v}
end
table.sort(pop_s, function (a,b) return a.sales>b.sales end)
for k,v in pairs(pop_s) do
print(v.item,v.sales)
end
result:
blue 3
red 2
green 1
To expand on Mike's answer: You could even sort the counts in linear (vs. O(n log n)) time since you know that the counts range from 1 to n; thus you can use a "bucket" approach where you use an index of products by count sold:
local products = {
["430373bb5b7a40a04f9"] = "red",
["0dce4263af4b5cfe0de"] = "red",
["cf2559afb736c1eb1bc"] = "green",
["abc4d248541c3386c88"] = "blue",
["bb9386c65270948ebee"] = "blue",
["b193fba741cd646a9c0"] = "blue",
}
local counts = {}
for _, product in pairs(products) do
counts[product] = (counts[product] or 0) + 1
end
local prods_by_cnt = {}
local max_cnt = 0
for product, count in pairs(counts) do
prods_by_cnt[count] = prods_by_cnt[count] or {}
table.insert(prods_by_cnt[count], product)
max_cnt = math.max(max_cnt, count)
end
local prods_sorted = {}
for cnt = 1, max_cnt do
for _, prod in ipairs(prods_by_cnt[cnt]) do
table.insert(prods_sorted, prod)
end
end
Side note: There is no need to build tables {item = ..., sales = ...} as long as you have the counts table: You can just keep a table of item names and use the item names to index the counts table. This may be slightly slower in practice because the counts table is larger and thus presumably more expensive to index - on the other hand, it is more memory-efficient; in theory, both are equally fast and memory efficient, requiring a constant time for lookup of the sales / counts and constant space to store each count.
Try this:
local products = {}
products["430373bb5b7a40a04f9"] = "red"
products["0dce4263af4b5cfe0de"] = "red"
products["cf2559afb736c1eb1bc"] = "green"
products["abc4d248541c3386c88"] = "blue"
products["bb9386c65270948ebee"] = "blue"
products["b193fba741cd646a9c0"] = "blue"
function GetCommonItem(arr)
local Count = 0
local Product = null
for i, v in pairs(arr) do -- Loops through the table
local Temp = 0
for e, f in pairs(arr) do -- Loops again to count the number of common products
if f = v then
Temp += 1
if Temp >= Count then -- Picks the product if it's the most common one
Count = Temp
Product = f
end
end
end
end
return Product
end
print("Most Common Product: ".GetCommonItem(products))
Didn't test so not sure if it works! Let me know the results after u try it!

How can I shift all of the tables down after removing a table?

In this code:
t = {
num = '',
}
t[0].num = '0'
t[1].num = '1'
t[2].num = '2'
Is there a way for me to delete t[0], then shift all of the table's values down, so that afterword it looks like this:
t[0].num = '1'
t[1].num = '2'
Example with imaginary functions:
t = {
num = '',
}
t[0].num = '0'
t[1].num = '1'
t[2].num = '2'
for i=0,tableLength(t) do
print(t[i])
end
--Output: 012
remove(t[0])
for i=0,tableLength(t) do
print(t[i])
end
--Output: 12
t = {
num = '',
}
t[0].num = '0'
t[1].num = '1'
t[2].num = '2'
This code will cause errors for indexing t[0], a nil value.
t only has one field and that is t.num
You need to do something like this:
t = {}
for i = 0, 2 do
t[i] = {num = tostring(i)}
end
if you want to create the desired demo table.
As there are many useful functions in Lua that assume 1-based indexing you I'd recommend starting at index 1.
local t = {1,2,3,4,5}
Option 1:
table.remove(t, 1)
Option 2:
t = {table.unpack(t, 2, #t)}
Option 3:
t = table.move(t, 2, #t, 1, t)
t[#t] = nil
Option 4:
for i = 1, #t-1 do
t[i] = t[i+1]
end
t[#t] = nil
There are more options. I won't list them all. Some do it in place, some result in new table objects.
As stated in this answer, by creating a new table using the result of table.unpack:
t = {table.unpack(t, 1, #t)}

How can I merge two tables like this? - Lua

I have these tables set like this
local tableone = {["Gold"] = 10, ["Gem"] = 5}
local tabletwo = {["Level"] = 1}
This is the code for merging
local test = {tableone, tabletwo}
print(test)
But if I try to merge the tables then the output is like this
[1] = {
["Gold"] = 10,
["Gem"] = 5
},
[2] = {
["Level"] = 1
}
And I would like to have the output like this
[1] = {
["Gold"] = 10,
["Gem"] = 5,
["Level"] = 1
}
Is this possible?
Sorry if I'm not that good at explaining.
You can do this with a simple nested loop.
local function merge(...)
local result <const> = {}
-- For each source table
for _, t in ipairs{...} do
-- For each pair in t
for k, v in pairs(t) do
result[k] = v
end
end
return result
end
local t <const> = {merge(tableone, tabletwo)}
I put the result in a table constructor due to the [1] in the question.

Spawn specific objects from table in for loop - Corona

I have a table of objects that I spawn into a scrollview space, but at the moment its picking randomly when I would actually like to actually spawn in specific sets, for example:
[1] [2] [3] [1] [2] [3] [1] [2] [3] across the loop number.
I understand it would be something to do with removing the math.random to spawn 1 random object from the table, but I'm not sure how I could code it to do it in order of the table instead. Maybe its something simple I missed.
spawn table
local colorsData = {
{name = "Blue", img = "images/RectangleBlue#2x.png"},
{name = "Red", img = "images/RectangleRed#2x.png"},
{name = "Green", img = "images/RectangleGreen#2x.png"}
}
For loop
local spaceApart = 100
for idx = 1,11 do
local c = math.random(1, #colorsData)
local cd = colorsData[c]
local s = display.newImageRect(cd.img, 106,60)
s.name = cd.name
s.x = (idx * spaceApart)
s.y = (scrollView.height / 2)
physics.addBody(s, { isSensor = true })
s:addEventListener ("tap", levelTapped)
scrollView:insert(s)
end

How to run table and print a specific key

I have a table:
employee = {
name = "John", age = 30,
name = "George", age = 35
}
Now, I want to run the whole table, and if the name "George" is found, then the appropriate age to be printed. How can I do this? From what I searched I found that you can run a list with the code for k, v in pairs(employee) do but I don't know how to continue from there.
Your table will need to be restructured to start off with.
employee = {
{name = "John", age = 30},
{name = "George", age = 35},
}
This will allow the age to always match up with the name. Then you could run:
for _,v in ipairs(employee) do
if v.name == "George" then
return v.age
end
end
You can even create it as a function so you can check whatever name you want:
function find_age(n)
for _,v in ipairs(employee) do
if v.name == n then
return v.age
end
end
end
Of course, this will return the age of every n in the table, though.
Updated for comment
You can do it with a function as well.
function add_employee(n,a)
table.insert(employee, {name = n, age = a})
end

Resources