Thezi
Thezi

Reputation: 159

Is there a non-hacky way to change a value in a nested table given a table of the keys?

So I am trying to change a value in a nested table given a table of the keys

Example:

local DATA = {
    Storage = {
        Person_id = {
            Money = 0;
            Inventory = {
                Item1 = 0;
            }
        }
    }
}

local function ChangeData(ID, KeyTable, Value, Operation)
    local StorageValue = DATA.Storage[ID].Data; 
    for _, Key in ipairs(KeyTable) do
        StorageValue = StorageValue[Key];
    end

    if Operation == "+" then
        StorageValue = StorageValue + Value;
    elseif Operation == "=" then
        StorageValue = Value;
    end
end

ChangeData("person_id", {"Money"}, 5, "="};
ChangeData("person_id", {"Inventory", "Item1"}, 5, "="};

This is successful in getting the value from the nested table (and changing the variable value), but not changing the value in the nested table.

...

The only way to fix this (which I REALLY DO NOT wanna do) is to hard-code it. Ex:

if Operation == "=" then
   if #KeyTable == 1 then
      DATA.Storage[ID].Data[KeyTable[1]] = Value;
   elseif #KeyTable == 2 then
      DATA.Storage[ID].Data[KeyTable[1]][KeyTable[2]] = Value;
--... and so on

So what I am asking is: Is there a non-hacky way to change a value in a nested table given a table of the keys?

Upvotes: 2

Views: 188

Answers (1)

Nifim
Nifim

Reputation: 5031

You can remove the last value of the table using table.remove, and save that as your last key.

Then you can use your code mostly as is, just need to add the last key indexing to your operation if statement bodies.

   local DATA = {
      Storage = {
          Person_id = {
              Money = 0,
              Inventory = {
                  Item1 = 5
              }
          }
      }
  }

  local function ChangeData(ID, KeyTable, Value, Operation)
      local StorageValue = DATA.Storage[ID]
      local LastKey = table.remove(KeyTable)

      for i, Key in ipairs(KeyTable) do
          StorageValue = StorageValue[Key]
      end

      if Operation == "+" then
          StorageValue[LastKey] = StorageValue[LastKey] + Value
      elseif Operation == "=" then
          StorageValue[LastKey] = Value
      end
  end

  ChangeData("Person_id", {"Money"}, 5, "=")
  ChangeData("Person_id", {"Inventory", "Item1"}, 5, "+")

  print(DATA.Storage.Person_id.Money)
  print(DATA.Storage.Person_id.Inventory.Item1)

Also ,as stated by Egor Skriptunoff in the comments, be sure to change next, KeyTable to ipairs(KeyTable) to insure your key order is preserved.

Upvotes: 2

Related Questions