以值比對

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 (diff)