molevision
molevision

Reputation: 23

Editing multidimensional table with uncertain dimensions in Lua

I want to be able to access and edit values in a user-generated table, that can have any number of dimensions.

Say, for this nested table,

table = {
    '1',
    {
        '2.1',
        '2.2'
    },
    {
        {
            '3.1.1',
            '3.1.2'
        },
        '3.2'
    },
}

I would have another table that contains a location for the needed data,

loc = {3, 1, 2}

Ideally, what I'd want is to be able to not only access but edit the values in the table, similar to using table[3][1][2] but by utilizing the loc table,

print(table[loc[1]][loc[2]][loc[3]]) --returns 3.1.2
print(table[loc]) --hypothetically something like this that takes each indexed member of the table in order

I also want to be able to edit this table.

table[loc] = {'3.1.2.1', '3.1.2.2'}

I need to be able to edit the global table, so cannot use the methods listed in this reddit thread, and haven't been able to find the right way to use metatables for this yet. I appreciate the help, thanks.

Upvotes: 2

Views: 92

Answers (1)

Robert
Robert

Reputation: 2812

I think you could simply write an additional function for this purpose.

function TreeGetValue (Tree, Location)

  local CorrectTree = true
  local Index       = 1
  local Dimensions  = #Location
  local SubTable    = Tree
  local Value

  -- Find the most deep table according to location
  while (CorrectTree and (Index < Dimensions)) do
    local IndexedValue = SubTable[Location[Index]]
    if (type(IndexedValue) == "table") then
      SubTable = IndexedValue
      Index    = Index + 1
    else
      CorrectTree = false
    end
  end

  -- Get the last value, regarless of the type
  if CorrectTree then
    Value = SubTable[Location[Index]]
  end
  
  return Value
end

Here, we assume that the tree is well-formatted as the beginning. If we find any problem we set the flag CorrectTree to false in order to stop immediately.

We need to make sure we have a table at every dimension in order index a value from.

> TreeGetValue(table, loc)
3.1.2

Obviously, it's also easy to to write the set function:

function TreeSetValue (Tree, Location, NewValue)

  local Index      = 1
  local Dimensions = #Location
  local SubTable   = Tree

  -- Find the most deep table according to location
  while (Index < Dimensions) do
    local IndexedValue = SubTable[Location[Index]]

    -- Create a new sub-table if necessary
    if (IndexedValue == nil) then
      IndexedValue = {}
      SubTable[Location[Index]] = IndexedValue
    end

    SubTable = IndexedValue
    Index    = Index + 1
  end

  -- Set or replace the previous value
  SubTable[Location[Index]] = NewValue
end

And then to test it with your test data:

> TreeGetValue(table, loc)
3.1.2
> TreeSetValue(table, loc, "NEW-VALUE")
> TreeGetValue(table, loc)
NEW-VALUE

Upvotes: 1

Related Questions