Search code examples
lualua-table

How to insert data and tables into an existing one?


I have a trouble inserting new rows and tables into an already existing one.

Lets call the source SourceFile.lua and its simplified contents:

SourceFile = {};

SourceFile.list = {
    BrandName1 = {
        number = 10,
        products = {
            "Product1", 3,
            "Product2", 4,
            "Product3", 7,
        },
    },
    BrandName2 = {
        number = 5,
        products = {
            "Product1", 10,
            "Product2", 3,
            "Product3", 6,
        },
    },
    -- and so on
}

I want to do something like this:

require 'SourceFile'

local myData = {
  BrandName2 = { -- add new products for the existing brand
    products = {
      "Product4", 2,
    },
  },
  MyBrandName1 = { -- add new brand
    number = 12,
    products = {
      "MyProduct1", 21,
      "MyProduct2", 95,
    },
  },
  -- and so on
}

table.insert(SourceFile.list, myData)

However there's something wrong in my code and I get the following result (printed with inspect):

{
  list = { {
      BrandName2 = {
        products = { "Product4", 2 }
      },
      MyBrandName1 = {
        number = 12,
        products = { "MyProduct1", 21, "MyProduct2", 95 }
      }
    },
    BrandName1 = {
      number = 10,
      products = { "Product1", 3, "Product2", 4, "Product3", 7 }
    },
    BrandName2 = {
      number = 5,
      products = { "Product1", 10, "Product2", 3, "Product3", 6 }
    }
  }
}

What am I doing wrong?

I'm new to lua and pretty sure that it's something obvious, but not for me. Please, help me.


Addition

After these answers I've also found a way to insert new brand names one by one:

SourceFile.list.MyBrandName1 = {
    number = 12,
    products = {
      "MyProduct1", 21,
      "MyProduct2", 95,
    },
}

This does not fully answer my question, but might be useful to someone new to lua.


Solution

  • table.insert adds its second argument to an array (its first argument). Your SourceFile.list is only supposed to have string keys, so it can't work as an array. You'll need a recursive function to merge the data from one table into the other:

    local function meld(data, newData)
      for k, v in pairs(newData) do
        local oldValue = data[k]
        if type(oldValue) ~= 'table' or type(v) ~= 'table' then
          -- One of the values is not a table, so let's clobber the old value.
          data[k] = v
        else
          -- Both are tables.
          meld(oldValue, v)
        end
      end
    end
    
    meld(SourceFile.list, myData)