所需值的完整路径 [英] Full path to the required value

查看:68
本文介绍了所需值的完整路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取表中所需值的完整路径?我想通过代理表跟踪另一个表中的变化.

How do I get the full path to the required value in the table? I want to track changes in another table through a proxy table.

我知道我需要在其中使用元表和__index.但是我还没有想出一个跟踪器.

I understand that I need to use metatables and __index in it. But I haven't been able to come up with a tracker yet.

示例表结构:

Objects = {
Panel = { layer = 1, x = 600, y = 328, w = 331, h = 491;
    objects = {
        label = { layer = 1, x = 0, y = 0, text = 'header' };
        Window = { layer = 2, x = 400, y = 100, w = 100, h = 100;
            objects = {
                label = { layer = 1, x = 0, y = 0, text = 'lorem ipsum dorem' };
            };
        };
    };
};
};

路径:Objects.Panel.objects.Window.objects.label.text

Path: Objects.Panel.objects.Window.objects.label.text

我试图为每个表创建一个元表并将每个对__index的调用的结果收集到一个表中,以便大致了解检索或更改了哪些键和值,以便将这些值与其他表同步

I tried to create a metatable for each of the tables and collect the result of each call to __index into a table in order to roughly understand which key and value were retrieved or changed in order to synchronize these values ​​with other tables.

推荐答案

这将证明其运行缓慢且内存效率低下.无论如何,您是正确的:代理并根据自己的喜好处理 __ index __ newindex 元方法.话虽如此,您还需要以某种方式跟踪代理的状态.

This will prove itself to be horrendously slow and memory inefficient. Anyway, you were right on the track: proxy and handle __index and __newindex metamethods to your liking. This being said you also need to track the state of the proxy somehow.

您可以尝试使用一些闭包和高值来隐藏它,但是简单的方法是将信息直接存储在代理表中:

You can try to hide it with some closures and upvalues but the easy way is to store the information directly in the proxy tables:

function make_tracker (o, name)
  local mt = {}
  mt.__index = function (proxy, key)
    local path = {unpack(rawget(proxy, "__path"))} -- Stupid shallow copy
    local object = rawget(proxy, "__to")
    table.insert(path, key)
    if type(object[key]) == "table" then
      return setmetatable({__to = object[key], __path = path}, mt)
    else
      return table.concat(path, ".") .. " = " .. tostring(object[key])
    end
  end
  return setmetatable({__to = o, __path = {name}}, mt)
end

__ to 字段指示代理应该指向哪个代理,并且 __ path 可以覆盖到目前为止我们已经侵入的字段.它会进行浅表复制,以便可以使用具有局部变量的子代理.参数 name 用于初始化第一个表的名称,因为您根本不知道这一点.您可以这样使用它:

__to fields indicates what proxy should point to and __path is there to cover fields we have trespassed so far. It does a shallow copy, so that one can use subproxies with local variables. name parameter is there to initialize the name of the first table, as you just simply can't know that. You use it like this:

local tObjects = make_tracker(Objects, "Objects")
local subproxy = tObjects.Panel.objects.Window
print(subproxy.objects.label.text)
print(tObjects.Panel.objects.label.text)
print(subproxy.x)

-- prints:
-- Objects.Panel.objects.Window.objects.label.text = lorem ipsum dorem
-- Objects.Panel.objects.label.text = header
-- Objects.Panel.objects.Window.x = 400

当然,我怀疑您想要的是将路径附加到原始值.修改 else 块的内部:

Of course, I doubt that appending the path to the original value is what you want. Modify insides of else block:

return table.concat(path, ".") .. " = " .. tostring(object[key])

根据您的需求,例如:

register_tracked_path(table.concat(path, "."))
return object[key]

如果要处理值的修改,则需要使用类似的 __ newindex 扩展元表.

If you want to handle modification of values you need to extend the metatable with similar __newindex.

这篇关于所需值的完整路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆