String to access nested table value.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
VEXED
Prole
Posts: 6
Joined: Fri Jun 26, 2020 5:22 pm
Contact:

String to access nested table value.

Post by VEXED »

The question I have is more of a Lua specific question, so hopefully I am alright to ask here.

Lua has two main ways of accessing a key in a table that I know of.

Code: Select all

local t = {x=0, y=5, other={z=10}}

-- Both should print "0"
print(t["x"])
print(t.x)

-- "x" can also be a variable
local prop = "x"
-- First prints "0". Second prints "nil"
print(t[prop])
print(t.prop)
This all works fine and is simple enough, but I am wanting to do a nested access with a single . seperated string.

Code: Select all

local t = {x=0, y=5, other={z=10}}
local zprop = "other.z"

-- This prints "nil"
print(t.zprop)
I'm sure I could loop through and seperate each . seperated value into a table. Then loop that to access the value, but I was wondering if a more sane way of doing this existed.

Thanks for any advice.
I make open source games, tools, and assets: https://vexed.zone/.
User avatar
GVovkiv
Prole
Posts: 46
Joined: Fri Jan 15, 2021 7:29 am

Re: String to access nested table value.

Post by GVovkiv »

Code: Select all

local t = {x=0, y=5, other={z=10}}
local zprop = "other"

-- This prints 10
print(t[zprop].z)
User avatar
VEXED
Prole
Posts: 6
Joined: Fri Jun 26, 2020 5:22 pm
Contact:

Re: String to access nested table value.

Post by VEXED »

GVovkiv wrote: Mon Apr 19, 2021 3:33 pm

Code: Select all

local t = {x=0, y=5, other={z=10}}
local zprop = "other"

-- This prints 10
print(t[zprop].z)
Thanks for the reply.

This isn't what I'm asking. I want to combine multiple keys into one string and access a nested table key with a single string. That or parse a string to access them.

In your example I still have to go in and specify the key of "z". Rather I want to just put all of that into one string of "other.z"
I make open source games, tools, and assets: https://vexed.zone/.
User avatar
pgimeno
Party member
Posts: 2610
Joined: Sun Oct 18, 2015 2:58 pm

Re: String to access nested table value.

Post by pgimeno »

There isn't a direct route. At best, you can make a function to do this kind of access, but it's not the path I'd recommend to follow:

Code: Select all

local function nested(table, index)
  for s in index:gmatch("[^%.]+") do
    table = table[s]
  end
  return table
end

local t = {x=0, y=5, other={z=10}}
local zprop = "other.z"

print(nested(t, zprop)) -- prints 10
I'd advise you to look for alternatives. It's not immediately clear what your plans are, so I can't suggest any.
grump
Party member
Posts: 721
Joined: Sat Jul 22, 2017 7:43 pm

Re: String to access nested table value.

Post by grump »

VEXED wrote: Mon Apr 19, 2021 3:17 pm but I was wondering if a more sane way of doing this existed.
We could have a talk about your definition of "sane" now, but I have this instead:

Code: Select all

local function sanelookup(t, path)
    for s in path:gmatch('[^.]+') do
        t = t[s]
    end
    return t
end

local t = {x=0, y=5, other={z=10}}
local zprop = "other.z"
print(sanelookup(t, zprop))
There are ways to automate this for selected tables, but I would strongly object to any of that.

edit: damn ninjas
User avatar
VEXED
Prole
Posts: 6
Joined: Fri Jun 26, 2020 5:22 pm
Contact:

Re: String to access nested table value.

Post by VEXED »

pgimeno wrote: Mon Apr 19, 2021 5:07 pm There isn't a direct route. At best, you can make a function to do this kind of access, but it's not the path I'd recommend to follow:

I'd advise you to look for alternatives. It's not immediately clear what your plans are, so I can't suggest any.
Hey, thanks a bunch this was very useful. Also thanks grump.

I'm now realizing that a "nested" table setter is something that I need as well (this seems 10x more confusing to do). Let me provide some explanation of what I'm attempting as to hopefully get some more clear direction on what to do.

My application takes in json that defines basics of "objects" in my app. This JSON is converted to a table, and then the code is highly generic code for handling some of these table values. Let me give an example here.

Code: Select all

{
  "object": {
    "width": 32,
    "height": 32,

    "position": {
      "x": 128,
      "y": 128
    },

    "movement": {
      "vvel": 0,
      "hvel": 0,
      "hspd": 4,
      "vspd": 4
    },

    "held": {
      "up": {"movement.vvel": -1},
      "down": {"movement.vvel": 1},
      "left": {"movement.hvel": -1},
      "right": {"movement.hvel": 1}
    }
  }
}
I just stripped a lot of values from the JSON above, so hopefully I haven't botched the syntax.

Anyhow, the main thing to focus on is the "held" table. I have designed a few tables that my code deals with for key press, hold, and release. They work fine but the problem I'm having is using them to set nested values. As seen above I am trying to set values in the tables movement sub table. This is a string I would like to handle in my games logic that parses through to my table above's specified value and sets it.

It works fine when say modifying the width that isn't in a sub table. Once I get to this nested issue it becomes quite nasty to deal with.

This might be different enough from the original topic to warrant a new topic, but i'll post here first.
I make open source games, tools, and assets: https://vexed.zone/.
grump
Party member
Posts: 721
Joined: Sat Jul 22, 2017 7:43 pm

Re: String to access nested table value.

Post by grump »

Code: Select all

local function saneset(t, path, value)
    local p, k
    for s in path:gmatch('[^.]+') do
        k, p, t = s, t, t[s]
    end
    p[k] = value
end
Can I ask where those JSON files come from? Are you writing them by hand?
User avatar
pgimeno
Party member
Posts: 2610
Joined: Sun Oct 18, 2015 2:58 pm

Re: String to access nested table value.

Post by pgimeno »

It's weird to have movement defined in such a file. Usually, movement needs custom logic - handling collisions, at least. There may be types of movements that you handle separately, but I'd rather have a field "movement_type" or something like that for these cases. Then your code would have the movement part hardcoded. Like, if you call this "straightforward", the implementation could be similar to this:

Code: Select all

if object.movement_type == "straightforward" then
  object.movement.hvel = 0
  object.movement.vvel = 0
  if held("up") then
    object.movement.vvel = object.movement.vvel - 1
  end
  if held("down") then
    object.movement.vvel = object.movement.vvel + 1
  end
  if held("left") then
    object.movement.hvel = object.movement.hvel - 1
  end
  if held("right") then
    object.movement.hvel = object.movement.hvel + 1
  end
elseif object.movement_type == "another type" then
  ...
end
Post Reply

Who is online

Users browsing this forum: No registered users and 25 guests