Search code examples
lua

Get sum of matched string values in lua


local currentTable ={
{apple = 2, mango = 3},
{apple = 3, mango = 7},
{apple = 1}}

local strings = {'apple', 'mango'}
local newTable = {}

local s = 0
function sum(str,data)
  for i, x in pairs(data) do
    if i == str then
        print(str)
        s = s + x
    end
  end
  return s
end

for k,v in pairs(currentTable) do
  if strings[k] then
    newTable[strings[k]] = sum(strings[k], v)
  end
end

for k,v in pairs(newTable) do
  print(k,v)
  --desired output: newTable = {apple = 6, mango = 10}
  --but it's giving me: newTable = {apple = 2, mango = 9}
end

I want to fill the newTable with the sum of specific key values. Been doing this for hours but can't seem to make it work. Thanks for your help.


Solution

  • Both currentTable and strings are array-like tables. This means they have numerical indices, starting at 1 and ending with N, where N is the length of the table.

    Very verbosely:

    local currentTable = {
        [1] = {apple = 2, mango = 3},
        [2] = {apple = 3, mango = 7},
        [3] = {apple = 1}
    }
    
    local strings = {
        [1] = 'apple',
        [2] = 'mango'
    }
    

    The keys in both tables are numbers. The values in currentTable are tables, and the values in strings are strings.

    This loop

    for k, v in pairs(currentTable) do
    

    means that strings[k] is indexing strings with numerical indices based on currentTable. This is problematic because

    if strings[k] then
        newTable[strings[k]] = sum(strings[k], v)
    end
    

    only attempts to sum tables (v) whose indices (k) exist in strings.

    Basically, you are always skipping the third table in currentTable because strings[3] is nil.


    s should be local to sum, otherwise it will keep its value from the previous calls to sum.


    For every string in strings you should check each table in currentTable for a key that matches.

    Consider the following cursory example:

    local function sum(baskets, fruits)
        local result = {}
    
        -- for every fruit we are interested in
        for _, fruit in ipairs(fruits) do
            result[fruit] = 0 -- create the sum
    
            -- for every basket (collection of fruits)
            for _, basket in ipairs(baskets) do
                -- if the basket contains the currently interesting fruit
                if basket[fruit] then
                    -- add its count to our current sum
                    result[fruit] = result[fruit] + basket[fruit]
                end
            end
        end
    
        return result
    end
    
    local my_fruit_baskets = {
        { apple = 2, mango = 3 },
        { apple = 3, mango = 7 },
        { apple = 1 }
    }
    
    local interesting_fruits = { 'apple', 'mango' }
    
    local total_fruits = sum(my_fruit_baskets, interesting_fruits)
    
    for name, count in pairs(total_fruits) do
        print(name, count)
    end
    

    Result:

    mango   10
    apple   6