按值比较

lua-users home
wiki

下面的 hashed 函数为给定的表 t 添加了一个元表,因此表中的任何写入或读取操作实际上都会使用键的哈希值而不是键本身。这允许模拟按值比较键。为了实现这一点,请确保应该具有相同值的两个对象(表或用户数据)具有相同的哈希值。

local function gethash(k)
  local hash = k
  local mt = getmetatable(k)
  local __hash = mt and mt.__hash
  if type(__hash)=='function' then
    hash = __hash(k)
  elseif type(__hash)~='nil' then
    hash = __hash
  end
  return hash
end

function hashed(t)
  return setmetatable(t, {
    __index = function(t, k)
      return t[gethash(k)]
    end,
    __newindex = function(t, k, v)
      rawset(t, gethash(k), v)
    end,
  })
end

-- example usage

local t1 = setmetatable({}, {__hash = 42})
local t2 = setmetatable({}, {__hash = 42})

local t = {}
t[t1] = "foo"
assert(t[t2]==nil)

t = hashed({})
t[t1] = "foo"
assert(t[t2]=="foo")
t[t2] = "bar"
assert(t[t1]=="bar")

这里有一个替代实现 - DavidManura

local mt = {
  __mode = 'kv',
  __index = function(t,k) return k end
}
local function newkeymap(t) return setmetatable(t or {}, mt) end

function hashed(t, keymap)
  return setmetatable(t, {
    __index    = function(t, k) return rawget(t, keymap[k]) end,
    __newindex = function(t, k, v) rawset(t, keymap[k], v) end,
  })
end

-- example usage

local t = {}
t.BAR = "foo"
assert(t.bar==nil)

local keymap = newkeymap { BAR = 'bar' }
t = hashed({}, keymap)
t.bar = "foo"
assert(t.BAR=="foo")
t.BAR = "bar"
assert(t.bar=="bar")

最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2008 年 9 月 5 日凌晨 2:22 GMT (差异)