米斯特利亚Wiki正在建设中,本WIKI编辑权限开放!欢迎参与~!

全站通知:

模块:Get/doc

来自米斯特利亚WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

这是模块:Get的文档页面

(MIT协议)

本模块灵感来源于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[?@.price<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