Lua:大小寫不敏感引用table鍵及遞歸設置元表

Lua:大小寫不敏感引用table鍵及遞歸設置元表

Lua中table的鍵是區分大小寫的,即:

local t = {}
t.a = "a"
print(t.A) -- nil

有時候希望可以大小寫不敏感地訪問、引用table的鍵,可以通過設置元表實現:

local t = {}
t.a = "a"
t.B = "B"
t.c = "c"

local mt = {}
mt.__index = function(t, k)
	local v
	-- t中含大量鍵時開銷極大
	for tk, tv in pairs(t) do
		-- 大小寫不敏感比較鍵
		if string.lower(tk) == string.lower(k) then
			v = tv
			break
		end
	end
	return v
end

setmetatable(t, mt)

-- 正常調用
print(t.a) -- a
-- 小寫轉大寫調用
print(t.b) -- B
-- 大寫轉小寫調用
print(t.C) -- c

有兩個問題:

1.這樣的代碼僅適用於功能,不適用於性能。

當t中包含的鍵非常多時,而我們恰好觸發原方法__index,就導致一次遍歷。

這樣做開銷極大,在上量跑壓力時有很大的問題。(耗費大量CPU做遍歷)

2.只針對t有效,t的子孫table,沒有設置元表,仍然大小寫敏感。

於是我們需要“遞歸設置元表”。


我這裏指的是,將一個元表設置到某個table,以及table中所有的子孫table。

local mt = {}
mt.__index = function(t, k)
	local v
	-- t中含大量鍵時開銷極大
	for tk, tv in pairs(t) do
		-- 大小寫不敏感比較鍵
		if string.lower(tk) == string.lower(k) then
			v = tv
			break
		end
	end
	return v
end

-- 遞歸設置元表
function recurrence_setmetatable(t, mt)
	if type(t) ~= "table" then
		return
	end

	-- 設置table元表
	setmetatable(t, mt)

	-- 遞歸table設置子元表
	for _, tv in pairs(t) do
		if type(tv) == "table" then
			recurrence_setmetatable(tv, mt)
		end
	end
end

local t = {}
t.test1024 = {}
t.test1024.test1280 = {}
t.test1024.test1280.key = "value"
t.a = "a"

recurrence_setmetatable(t, mt)

print(t.TEST1024.TEST1280.KEY) -- value
print(t.a) -- a
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章