切換菜單
切換偏好設定選單
切換個人選單
尚未登入
登入後可編輯和留言。

此頁面為 Module:Get 的說明文件

本模塊靈感來源於JSONPath。

假設有這樣一個數據:

data = {
	store = {
		books = {
			{
				category = "reference",
				author = "Nigel Rees",
				title = "Sayings of the Century",
				price = 8.95
			},
			{
				category = "fiction",
				author = "Evelyn Waugh",
				title = "Sword of Honour",
				price = 12.99
			},
			{
				category = "fiction",
				author = "Herman Melville",
				title = "Moby Dick",
				isbn = "0-553-21311-3",
				price = 8.99
			},
			{
				category = "fiction",
				author = "J. R. R. Tolkien",
				title = "The Lord of the Rings",
				isbn = "0-395-19395-8",
				price = 22.99
			}
		},
		bicycle = {
			color = "red",
			price = 399
		}
	}
}

用法:

> local get = require('Module:Get')

> -- 获取data.store.books的所有子项的author(JSONPath:$.store.books[*].author)
> get(data).store.books:items().author()
{"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien"}

> -- 获取data内任意深度的author(JSONPath:$..author)
> get(data)._.author()
{"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien"}

> -- 获取data.store内任意深度的price(JSONPath:$.store..price)
> get(data).store._.price()
{8.95, 12.99, 8.99, 22.99, 399}

> -- 获取data.store内任意深度的books的第3个子项(JSONPath:$..book[2])
> get(data)._.books[3]()
{{ category = "fiction", author = "Herman Melville", title = "Moby Dick", isbn = "0-553-21311-3", price = 8.99 }}

> -- 获取data内任意深度的books的子项中满足price < 10的项目(JSONPath:$..books[[email protected]<10]
> get(data)._.books[function (x) return x.price < 10 end]()
{
	{ category = "reference", author = "Nigel Rees", title = "Sayings of the Century", price = 8.95 },
	{ category = "fiction", author = "Herman Melville", title = "Moby Dick", isbn = "0-553-21311-3", price = 8.99 },
}

get(...)

get(...)返回一個Getter對象,可以傳多個值。

> get(data)._.author()
{"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien"}

> get(data, { author = "Foo" }, { bar = { author = "Bar" } })._.author()
{"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien", "Foo", "Bar"}

特別地,對於get函數返回的Getter對象,它迭代時將依次返回每個非nil參數,因此你可以這樣用get函數:

for v in get('a', 'b', nil, 'd') do  -- 或 get('a', 'b', nil, 'd'):generate()
	print(i, v)
end
--[[ 输出:
a
b
d
]]

方法

每個Getter對象都有以下方法:

非鏈式調用方法

:all()

返回一個包含查找到的值的列表。該列表具有table庫的方法,以及一個字段n表示列表長度。

> get(data).store.books:items().author:all()
> get(data).store.books:items().author()  -- 简写,建议仅在整个表达式写在一行时使用
{"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien"}

> get(data).store.books:items().author:all():concat(" & ")
Nigel Rees & Evelyn Waugh & J. R. R. Tolkien & J. R. R. Tolkien

:one()

返回結果中的第一個值,如果不存在則返回nil

> get(data).store.books:items().author:one()
"Nigel Rees"

:must_one([message])

返回結果中的第一個值,如果不存在則報錯。

> get(data).store.books:items().author:one()
"Nigel Rees"

:unpack()

解包,類似Lua標準庫的unpack(在5.2及以上版本中為table.unpack)。

> get(data).store.books:items().author:unpack()
"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien"

:iterate()

:all()返回的是一個包含了所有結果的列表,而:iterate()的返回值能用於for循環。

-- 第一个值必须忽略,即`_`,它存储了内部信息,使用者完全用不上这个值
for _, author in get(data).store.books:items().author:iterate() do print(author) end
-- `:iterate()` 可以省略且推荐省略,上下两行代码等价
for _, author in get(data).store.books:items().author do print(author) end
--[[ 输出:
Nigel Rees
Evelyn Waugh
J. R. R. Tolkien
J. R. R. Tolkien
]]

:generate()

返回一個迭代器函數,每次調用將得到下一個結果,直到所有結果都返回(該迭代器是有副作用的,即非純函數的)。該方法與:iterate()類似,可用於for循環,區別是該方法返回的迭代器函數不會輸出內部狀態。

在且僅在for循環中,:generate()可以省略,更推薦省略,除非查詢結果(注意是查詢結果而不是待查數據)有非常多,多到影響性能。

for author in get(data).store.books:items().author:generate() do print(author) end
for author in get(data).store.books:items().author do print(author) end  -- 省略:generate()
--[[ 输出:
Nigel Rees
Evelyn Waugh
J. R. R. Tolkien
J. R. R. Tolkien
]]

鏈式調用方法

鏈式調用方法將返回一個Getter對象。

:field(key)

獲取字段的值,一般不需要用這個方法,直接.xxx即可。而當字段的鍵為'_'或函數時,只有調用此方法才能獲取到該鍵對應的值,因為'_'被「獲取任意深度的值」的語法佔用(如get(data).store._.price),後者被filter的簡寫佔用。

local data = {
	_ = {
		foo = 'A',
	},
	another = {
		bar = {
			foo = 'B',
		},
	},
}
get(data)._.foo()           --> {'A', 'B'}
get(data):field('_').foo()  --> {'A'}

:filter(predict)

過濾。

> get(data)._.books:items():filter(function (x) return x.price < 10 end).title()
> get(data)._.books[function (x) return x.price < 10 end].title()  -- 这是一个针对数组的简写,与上面等价
{"Sayings of the Century", "Moby Dick"}

> get(data)._:filter(function (x) return type(x) == "number" end)()
{8.95, 12.99, 8.99, 22.99, 399}

:items([filter])

獲取列表的每個項目。如果filter參數不為空,則相當於:items():filter(filter)

> get(data).store.books:items().author()
{"Nigel Rees", "Evelyn Waugh", "J. R. R. Tolkien", "J. R. R. Tolkien"}

:values([filter])

獲取表的每個值,包括列表部分和字典部分。如果filter參數不為空,則相當於:values():filter(filter)

> get(data).store.books[1]:values()()
{"reference", "Nigel Rees", "Sayings of the Century", 8.95}

:map(mapper)

轉換每個數據。

> for _, lowered_title in get(data)._.title:map(function (title) return title:lower() end) do print(lowered_title) end
sayings of the century
sword of honour
moby dick
the lord of the rings