Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble manipulating Lua tables

Let's say I have two tables:

veggie_multiples = {
{veggie = "carrot", quantity = 1},
{veggie = "tomato", quantity = 2},
{veggie = "celery", quantity = 3}}

veggie_singles = {
{veggie = "celery"},
{veggie = "carrot"},
{veggie = "potato"},
{veggie = "carrot"},
{veggie = "potato"}}

I'd like to end up with one table that represents:

veggie_multiples = {
{veggie = "carrot", quantity = 3},
{veggie = "tomato", quantity = 2},
{veggie = "celery", quantity = 4},
{veggie = "potato", quantity = 2}}

I tried something like:

veggie_multiples = {
{veggie = "carrot", quantity = 1},
{veggie = "tomato", quantity = 2},
{veggie = "celery", quantity = 3}}

veggie_singles = {
{veggie = "celery"},
{veggie = "carrot"},
{veggie = "potato"},
{veggie = "carrot"},
{veggie = "potato"}}

for i, n in ipairs(veggie_singles) do
    for ii, nn in ipairs(veggie_multiples) do
        if veggie_singles[i].veggie == veggie_multiples[ii].veggie then
            veggie_multiples[ii].quantity = veggie_multiples[ii].quantity + 1
            table.remove(veggie_singles, i)
        else
            table.insert(veggie_multiples, {veggie = veggie_singles[i], quantity = 1})
            table.remove(veggie_singles, i)
        end
    end
end

for i, n in ipairs(veggie_multiples) do
    print(veggie_multiples[i].veggie, " ", veggie_multiples[i].quantity)
end

I can't get it to work no matter what I try. Please help! Thank you.

like image 468
Eli Bell Avatar asked Jul 16 '26 03:07

Eli Bell


2 Answers

A for loop using ipairs iterates over the index and the value so for i, n in ipairs(veggie_singles) will give i=1 and n={veggie="celery"} in the first iteration and so on. The code need not use i so in Lua you use _ as a throw away. Then search for an entry in veggie multiples that has the same name as a veggie single. Add it if it is not found or increment quantity if found.

for _, vs in pairs(veggie_singles) do
    local found = false
    for _, vm in pairs(veggie_multiples) do
       if vm.veggie == vs.veggie then
          vm.quantity = vm.quantity + 1
          found = true
          break
       end
    end
    if not found then
        table.insert(veggie_multiples, {veggie=vs.veggie, quantity=1}) 
    end
end


for i, n in ipairs(veggie_multiples) do
    print(veggie_multiples[i].veggie, " ", veggie_multiples[i].quantity)
end

Since the indices are not very useful for the problem, and instead the name is what you want to find things by, you can use the names as the keys in the tables to simplify the code.

quantity = {carrot=1, tomato=2, celery=3}
add = {"celery", "carrot", "potato", "carrot", "potato"}

for _, v in pairs(add) do
   quantity[v] = (quantity[v] or 0) + 1
end

for veggie, qty in pairs(quantity) do
   print(veggie, qty)
end

which outputs:

potato  2
carrot  3
celery  4
tomato  2
like image 60
ryanpattison Avatar answered Jul 18 '26 07:07

ryanpattison


This works:

for i, n in ipairs(veggie_singles) do
    local existed = false
    for ii, nn in ipairs(veggie_multiples) do
        if veggie_singles[i].veggie == veggie_multiples[ii].veggie then
            veggie_multiples[ii].quantity = veggie_multiples[ii].quantity + 1
            existed = true
            break
        end
    end
    if not existed then
        table.insert(veggie_multiples, {veggie = veggie_singles[i].veggie, quantity = 1})
    end
end

Only when the item in veggie_singles[i].veggie isn't equal to all items in veggie_multiples, a new item is inserted. This is what the flag existed does.

like image 25
Yu Hao Avatar answered Jul 18 '26 05:07

Yu Hao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!