置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

Module:Luaq

猛汉♂百科,万男皆可猛的百科全书!转载请标注来源页面的网页链接,并声明引自猛汉百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [查看] [编辑] [历史] [刷新]

LUAQ是Lua Query的缩写,通过一系列查询函数让以Lua表(table)为主的数据源查询代码更加简洁。

使用配置

在模块代码中添加如下代码:

  1. require("Module:Luaq")

之后便可以通过luaq使用各种查询函数。

使用

本章节将会介绍LUAQ的基本概念、查询函数的文档说明以及使用时必须或可选的注意事项。

若您想要了解查询函数的实现细节,或者希望修改结构、添加更多查询函数,请参阅#开发章节。

基本概念

查询对象

查询对象是由LUAQ的查询函数按照某种规范生成的特殊对象,它的本质是Lua表,但由于其内部的结构对于使用者来说是未知的,所以无法通过一般的手段获取它的内部结构。

实际上,使用者没有必要尝试去获取它的内部结构,若要获取它包含的内容,请参阅#查询展开章节。

延迟查询

延迟查询是LUAQ的重要特征之一,它表现为——当查询对象被生成时,查询对象并不会立即展开。唯有调用某些查询函数时,查询对象才会被计算,并返回查询结果。

在“查询对象被生成时”和“调用立即展开查询对象的函数”之间,改变作为数据源的Lua表内容将对最终查询结果会造成影响;当查询对象被展开后,无论数据源发生任何改变,都不会改变查询结果。

#查询函数章节中,会立即展开查询对象的函数将注有说明。

查询展开

查询展开是指将包含了一系列指令的查询对象转化为结果的过程。一共有两种方式进行展开。

enum:

enum(query)

全局函数,返回展开查询对象的迭代器。

函数返回三个值:

  1. 迭代器函数
  2. 查询对象本身
  3. 0

迭代器用在泛型for循环中。

luaq.query:

请参阅luaq.query

查询函数调用格式

为了使代码更加直观简洁,LUAQ在Lua函数调用语法糖的基础上支持了更简洁的写法。以下两种写法是等价的:

函数:

luaq.<查询函数名称>(查询对象[, 参数1[, 参数2[..., 参数n]]])

语法糖:

查询对象:<查询函数名称>([, 参数1[, 参数2[..., 参数n]]])

当您使用了语法糖调用形式,并且遇到了莫名其妙的“函数“...”的第1个参数类型错误(应为table,实为...)。"”报错,不妨检查一下是否将:错写成了.

查询函数

luaq.query

luaq.query(query)

展开一个查询对象

这个函数将立即展开查询对象,并将查询结果包装为一个Lua表返回。
参数:
返回:
一个Lua表,其数值类型的键即为查询结果每一项的位置索引。

luaq.asQuery

luaq.asQuery(t)

将一个Lua表包装为查询对象

当参数t已经是查询对象时,将返回其本身。
参数:
  • t:一个Lua表。
返回:
一个查询对象
若参数t为一个查询对象时,函数将会返回t自身。
否则将会返回一个包装了t查询对象
错误:
  1. 函数“asQuery”的第1个参数类型错误(应为table,实为...)。":当参数t的值不是一个Lua表的时候抛出此错误。
示例:
  • 代码:
  1. <strong class="error"><span class="scribunto-error" id="mw-scribunto-error-0">脚本错误:函数“main”不存在。</span></strong>
  • 结果:
<strong class="error"><span class="scribunto-error" id="mw-scribunto-error-1">脚本错误:函数“main”不存在。</span></strong>

luaq.select

luaq.select(query, func)

对旧查询对象的每一个项进行指定的转换,并将结果形成新的查询对象。

参数:
  • query:一个查询对象,其每一个项将要被转换。
  • func:对query的每一个项进行的转换函数。转换函数将会接受到两个参数值:
    • 第1个参数值:query的当前项。
    • 第2个参数值:从开始到当前的索引。
返回:
一个查询对象。它由转换后的项组成。
错误:
  1. bad argument #2 to 'select' (table expected, got ...):当参数func的值不是一个函数的时候抛出此错误。
示例1:

在本示例中,转换函数返回当前项的值的类型。

  • 代码:
  1. <strong class="error"><span class="scribunto-error" id="mw-scribunto-error-2">脚本错误:函数“main”不存在。</span></strong>
  • 结果:
<strong class="error"><span class="scribunto-error" id="mw-scribunto-error-3">脚本错误:函数“main”不存在。</span></strong>
示例2:

在本示例中,luaq.select函数判断当前索引的奇偶性。若索引为奇数,则返回key字段的值;若索引为偶数,则返回value字段的值。

  • 代码:
  1. local t = { 5, 4, 3, str = "string" , 2, 1}
  2. local q = luaq.asQuery(t)
  3. :select(
  4. function(pair, i)
  5. if math.fmod(i, 2) == 1 then return pair.key
  6. else return pair.value
  7. end
  8. end
  9. )
  10. local r = q:query()
  11. for key, value in pairs(t) do
  12. print("key = "..key.."\tvalue = "..value)
  13. end
  14. print()
  15. print("查询结果:")
  16. for i, v in ipairs(r) do
  17. print(v)
  18. end
  • 结果:
key = 1         value = 5
key = 2         value = 4
key = 3         value = 3
key = 4         value = 2
key = 5         value = 1
key = str       value = string

查询结果:
1
4
3
2
5
string

luaq.where

luaq.where(query, func)

对旧查询对象的每一个项进行指定的筛选,并将符合条件的结果形成新的查询对象。

参数:
  • query:一个查询对象,其每一个项将要被筛选。
  • func:对query的每一个项进行检测的筛选函数。检测函数应返回truefalse,且将会接受到两个参数值:
    • 第1个参数值:query的当前项。
    • 第2个参数值:从开始到当前的索引。
返回:
一个查询对象。它由筛选后的项组成。
错误:
  1. bad argument #2 to 'where' (table expected, got ...):当参数func的值不是一个函数的时候抛出此错误。
示例:

本示例在luaq.select函数的示例1的基础上进行筛选。luaq.where函数的筛选机制为“项的值是字符串类型”或“项的值不小于3”。

  • 代码:
  1. local t = { 5, 4, 3, str = "string" , 2, 1}
  2. local q = luaq.asQuery(t)
  3. :select(
  4. function(pair)
  5. return type(pair.value)
  6. end
  7. )
  8. :where(
  9. function(e)
  10. return type(e) == "string" or e >= 3
  11. end
  12. )
  13. local r = q:query()
  14. for key, value in pairs(t) do
  15. print("key = "..key.."\tvalue = "..value)
  16. end
  17. print()
  18. print("查询结果:")
  19. for i, v in ipairs(r) do
  20. print(v)
  21. end
  • 结果:
key = 1         value = 5
key = 2         value = 4
key = 3         value = 3
key = 4         value = 2
key = 5         value = 1
key = str       value = string

查询结果:
4
3
5
string

luaq.count

luaq.count(query)

获取查询结果中项的数量。

这个函数将立即展开查询对象。
参数:
  • query:一个查询对象。
返回:
查询结果中项的数量。
示例:

本示例同时演示了LUAQ的延迟查询。表中含有6对值键对,因此第一次luaq.count查询的结果为6。

删去表中的第二个元素后,已通过调用luaq.query展开查询的变量r,其循环遍历输出的内容不变,但第二次luaq.count查询的结果变为5。

  • 代码:
  1. local t = { 5, 4, 3, str = "string" , 2, 1}
  2. local q = luaq.asQuery(t)
  3. local r = q:query()
  4. for i, pair in ipairs(r) do
  5. print(pair.key.."\t"..pair.value)
  6. end
  7. print("count() = "..q:count())
  8. print()
  9. table.remove(t, 2) --删去表中的第二个元素
  10. for i, pair in ipairs(r) do
  11. print(pair.key.."\t"..pair.value)
  12. end
  13. print("count() = "..q:count())
  • 结果:
1       5
2       4
3       3
4       2
5       1
str     string
count() = 6

1       5
2       4
3       3
4       2
5       1
str     string
count() = 5

luaq.any

luaq.all

luaq.distinct

luaq.groupBy

开发

本章节将会介绍LUAQ的实现细节、开发相关的文档说明等。

查询对象保留字段

查询对象本质是一个Lua表。为了判断一个Lua表是否为查询对象,同时为了实现LUAQ核心功能,该Lua表必须设置元表(metatable)并且遵守以下约束

  • __enum(必须)一个函数,返回查询对象的枚举器。
  • __reset(可选)一个函数,用于重置查询对象的状态。
  • __index(可选)一个函数,用于按数字索引获取对应的查询结果的项目。
  • __ipairs(可选)一个函数,用于重写_G.ipairs函数逻辑。
  • __pairs(可选)一个函数,用于重写_G.pairs函数逻辑。

除此之外,各个LUAQ查询函数生成的查询对象的元表也有各自的保留字段,请在开发中避免占用。

各查询函数的保留字段将分别说明。

枚举器

对每一个查询对象调用__getenumerator函数即可获得其枚举器。

枚举器是支持LUAQ延迟查询的基石,通过改变其内部的状态可以实现向前、向后查询等操作。

可以通过以下两种方式获取枚举器的对象:

  • 函数:

<查询对象>.__getenumerator(<查询对象>)

  • 语法糖:

<查询对象>:__getenumerator()

枚举器字段

枚举器是一个Lua表,为了正常工作,它必须具有以下字段:

  • current:这个字段的类型为函数,用以获取当前查询的项。
    调用:
    • 函数<枚举器对象>.current(self, query)
    • 语法糖<枚举器对象>:current(query)
    参数:
    self:即<枚举器对象>本身,用以支持语法糖调用。
    query:包含<枚举器对象>查询对象
    返回:
    当前查询的项。
  • moveLast:这个字段的类型为返回值为truefalse函数,用以将枚举器内部的状态向后回退一次。
    调用:
    • 函数<枚举器对象>.moveLast(self, query)
    • 语法糖<枚举器对象>:moveLast(query)
    参数:
    self:即<枚举器对象>本身,用以支持语法糖调用。
    query:包含<枚举器对象>查询对象
    返回:
    一个值,指示回退操作是否成功。
  • moveNext:这个字段的类型为返回值为truefalse函数,用以将枚举器内部的状态向前前进一次。
    调用:
    • 函数<枚举器对象>.moveNext(self, query)
    • 语法糖<枚举器对象>:moveNext(query)
    参数:
    self:即<枚举器对象>本身,用以支持语法糖调用。
    query:包含<枚举器对象>查询对象
    返回:
    一个值,指示前进操作是否成功。
  • saveState:这个字段的类型为函数,用以获取枚举器内部的当前状态。
    调用:
    • 函数<枚举器对象>.saveState(self, query)
    • 语法糖<枚举器对象>:saveState(query)
    参数:
    self:即<枚举器对象>本身,用以支持语法糖调用。
    query:包含<枚举器对象>查询对象
    返回:
    枚举器内部的当前状态。
  • resetState:这个字段的类型为函数,用以设置枚举器内部的当前状态。
    调用:
    • 函数<枚举器对象>.resetState(self, query, state)
    • 语法糖<枚举器对象>:resetState(query, state)
    参数:
    self:即<枚举器对象>本身,用以支持语法糖调用。
    query:包含<枚举器对象>查询对象
    state:要设置的枚举器内部的状态。

枚举器工作原理

  1. 获取查询对象query
  2. 通过query:__getenumerator()获取枚举器enumerator。除非特殊设计,一般的枚举器的初始状态为起点。
  3. 调用enumerator:moveNext(query)枚举器内部状态前进一次,若返回值为true,则继续下一步。
  4. 调用enumerator:current(query)获取当前的项current
  5. current进行后续处理。
示例:
  1. local query = luaq.asQuery({ 5, 4, 3, 2, 1 })
  2. local enumerator = query:__getenumerator()
  3. while enumerator:moveNext(query) do
  4. local current = enumerator:current(query)
  5. print(current.key.."\t"..current.value)
  6. end
结果:
1       5
2       4
3       3
4       2
5       1

查询函数实现细节

实现细节:linq.query

  1. _G.luaq = {
  2. util = {}
  3. }
  4. function luaq.util.errBadArgType(funcName, paramIndex, expectedType, arg)
  5. error(mw.ustring.format("函数“%s”的第%d个参数类型错误(应为%s,实为%s)。", funcName, paramIndex, expectedType, type(arg)))
  6. end
  7. function luaq.util.errBadArgValue(funcName, paramIndex, expectedValue, arg, message, ...)
  8. local gotValue = type(arg)
  9. if gotValue == "number" or gotValue == "string" or gotValue == "boolean" then gotValue = mw.dumpObject(arg) end
  10. if type(message) == "string" then
  11. message = mw.ustring.format(message,expectedValue, arg, ...)
  12. else
  13. message = mw.ustring.format("(应为%s,实为%s)", expectedValue, mw.dumpObject(arg))
  14. end
  15. error(mw.ustring.format("函数“%s”的第%d个参数的值错误%s。", funcName, paramIndex, message))
  16. end
  17. function luaq.util.equal(l, r)
  18. -- 对键的每一个项目进行相等比较。
  19. local maxIndex = math.max(select("#", unpack(l)), select("#", unpack(r)))
  20. for _index = 1, maxIndex do
  21. if l[_index] ~= r[_index] then
  22. return false
  23. end
  24. end
  25. return true
  26. end
  27. function luaq.util.compare(l, r)
  28. -- 对键的每一个项目进行大小比较。
  29. local maxIndex = math.max(select("#", unpack(l)), select("#", unpack(r)))
  30. -- 越靠前的项目遇到不相等时,则两个键的大小关系等于这两个项目的大小关系。
  31. for _index = 1, maxIndex do
  32. local le, re = l[_index], r[_index]
  33. if le < re then return -1
  34. elseif le > re then return 1
  35. end
  36. end
  37. return 0 -- 所有项目均相等,则两个键相等。
  38. end
  39. local function isQuery(t)
  40. if type(t) ~= "table" then return false end
  41. local mt = getmetatable(t)
  42. return type(mt) == "table" and type(mt.__enum) == "function" and (mt.__reset == nil or type(mt.__reset) == "function")
  43. end
  44. -- 查询对象的默认索引元函数。(必须提供缓存元函数的实现。)
  45. local function __index(query, k)
  46. if type(k) == "number" and k > 0 then
  47. local self = getmetatable(query)
  48. self:__cachetill(k) -- 计算查询结果到索引k的项并缓存。
  49. return self.__cache[k]
  50. end
  51. end
  52. -- 查询对象的默认枚举元函数。(必须提供索引元函数的实现。)
  53. local function __enum(query, index)
  54. index = index + 1
  55. local current = query[index]
  56. if current then
  57. return index, current
  58. end
  59. end
  60. -- 查询对象的默认有序迭代元函数。
  61. local function __ipairs(query)
  62. return getmetatable(query).__enum, query, 0
  63. end
  64. -- 查询对象的默认无序迭代元函数。
  65. local __pairs = __ipairs
  66. local function enext(query, index)
  67. local index, current = getmetatable(query).__enum(query, index)
  68. if current then
  69. return index, unpack(current)
  70. end
  71. end
  72. function _G.enum(query)
  73. if not isQuery(query) then luaq.util.errBadArgValue("enum", 1, "查询对象", t, "(不是%s)。") end
  74. return enext, query, 0
  75. end
  76. function _G.resetstate(query)
  77. if not isQuery(query) then luaq.util.errBadArgValue("enum", 1, "查询对象", t, "(不是%s)。") end
  78. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  79. if __reset then
  80. __reset(query) -- 调用重置元函数。
  81. end
  82. end
  83. -- 将一个Lua表的所有值键对包装成查询对象。
  84. function luaq.asQuery(t)
  85. if type(t) ~= "table" then luaq.util.errBadArgType("asQuery", 1, "table", t) end
  86. if isQuery(t) then return t end -- 已经是查询对象了,不再重复操作。
  87. local rtenum, rt, rtstate -- 内部表的枚举函数、固定值、以及初始状态。
  88. local mt = {
  89. __cache = {},
  90. __cachedone = false
  91. }
  92. mt.__index = __index
  93. mt.__cachetill = function(self, index)
  94. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  95. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  96. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  97. local c = self.__cache -- 获取缓存数组。
  98. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  99. if rtenum == nil then
  100. rtenum, rt, rtstate = _G.pairs(t) -- 获取内部表的枚举函数、固定值、以及初始状态。
  101. end
  102. if type(rtenum) ~= "function" then luaq.util.errBadArgValue("asQuery", 1, nil, nil, "(全局pairs函数返回意外的值,找不到迭代函数)") end
  103. local state = c[#c] -- 当前起始状态为缓存数组的最末项。
  104. if state then
  105. state = state[1] -- 取键为起始状态。
  106. else
  107. state = rtstate -- 使用内部表提供的初始值为起始状态。
  108. end
  109. local k, v = state, nil -- (优化)
  110. while index > #c do
  111. k, v = rtenum(rt, k)
  112. if k == nil then break end
  113. table.insert(c, { k, v }) -- 向缓存数组中插入新项。
  114. end
  115. if k == nil then self.__cachedone = true end -- 仅当没有下一个键时设置缓存完毕标识符。
  116. end
  117. mt.__enum = __enum
  118. mt.__reset = function(q)
  119. local self = getmetatable(q)
  120. self.__cache = {}
  121. self.__cachedone = false
  122. rtenum, rt, rtstate = nil, nil, nil
  123. end
  124. mt.__ipairs = __ipairs
  125. mt.__pairs = __pairs
  126. local qResult = {}
  127. luaq.util.attachLuaq(qResult, mt)
  128. return qResult
  129. end
  130. -- 将一个Lua表的第一个不包含nil的序列包装成查询对象。
  131. function luaq.iasQuery(t)
  132. if type(t) ~= "table" then luaq.util.errBadArgType("iasQuery", 1, "table", t) end
  133. if isQuery(t) then return t end -- 已经是查询对象了,不再重复操作。
  134. local rtenum, rt, rtstate -- 内部表的枚举函数、固定值、以及初始状态。
  135. local mt = {
  136. __cache = {
  137. states = {} -- 保存状态的数组。
  138. },
  139. __cachedone = false
  140. }
  141. mt.__index = __index
  142. mt.__cachetill = function(self, index)
  143. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  144. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  145. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  146. local c = self.__cache -- 获取缓存数组。
  147. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  148. if rtenum == nil then
  149. rtenum, rt, rtstate = _G.ipairs(t) -- 获取内部表的枚举函数、固定值、以及初始状态。
  150. end
  151. if type(rtenum) ~= "function" then luaq.util.errBadArgValue("iasQuery", 1, nil, nil, "(全局ipairs函数返回意外的值,找不到迭代函数)") end
  152. local state, v
  153. if #c.states > 0 then
  154. state = c.states[#c.states] -- 当前起始状态为状态数组的最末项索引(或数组长度)。
  155. else
  156. state = rtstate -- 使用内部表提供的初始值为起始状态。
  157. end
  158. while index > #c do
  159. state, v = rtenum(rt, state)
  160. if v == nil then break end
  161. table.insert(c, { v }) -- 向缓存数组中插入新项。
  162. table.insert(c.states, state) -- 向状态数组中插入新项。
  163. end
  164. if v == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  165. end
  166. mt.__enum = __enum
  167. mt.__reset = function(q)
  168. local self = getmetatable(q)
  169. self.__cache = {
  170. states = {}
  171. }
  172. self.__cachedone = false
  173. rtenum, rt, rtstate = nil, nil, nil
  174. end
  175. mt.__ipairs = __ipairs
  176. mt.__pairs = __pairs
  177. local qResult = {}
  178. luaq.util.attachLuaq(qResult, mt)
  179. return qResult
  180. end
  181. -- 将可变参数序列包装成查询对象。
  182. function luaq.asQueryFrom(...)
  183. local rt = { ... }
  184. local count = select("#", unpack(rt)) -- 获取可变参数序列的长度。
  185. local mt = {
  186. __cache = {},
  187. __cachedone = false
  188. }
  189. mt.__index = __index
  190. mt.__cachetill = function(self, index)
  191. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  192. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  193. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  194. local c = self.__cache -- 获取缓存数组。
  195. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  196. local state = #c -- 当前起始状态为缓存数组的最末项索引(或数组长度)。
  197. while index <= count and index > state do
  198. local v = rt[state + 1]
  199. table.insert(c, { v }) -- 向缓存数组中插入新项。
  200. state = state + 1
  201. end
  202. if state == count then self.__cachedone = true end -- 仅当缓存数组长度与可变参数序列长度一致时设置缓存完毕标识符。
  203. end
  204. mt.__enum = __enum
  205. mt.__reset = nil -- 常量可变参数序列不再变化,无重置必要。
  206. mt.__ipairs = __ipairs
  207. mt.__pairs = __pairs
  208. local qResult = {}
  209. luaq.util.attachLuaq(qResult, mt)
  210. return qResult
  211. end
  212. function luaq.select(query, func)
  213. if type(query) == "table" then
  214. if not isQuery(query) then
  215. query = luaq.iasQuery(query)
  216. end
  217. else
  218. luaq.util.errBadArgValue("select", 1, "查询对象", query, "(不是%s)。")
  219. end
  220. if type(func) ~= "function" then luaq.util.errBadArgType("select", 2, "function", func) end
  221. local iqenum, iq -- 内部查询对象的枚举元函数以及固定值。
  222. local mt = {
  223. __cache = {},
  224. __cachedone = false
  225. }
  226. mt.__index = __index
  227. mt.__cachetill = function(self, index)
  228. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  229. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  230. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  231. local c = self.__cache -- 获取缓存数组。
  232. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  233. if iqenum == nil then
  234. iqenum, iq = getmetatable(query).__enum, query -- 获取内部查询对象的枚举元函数以及固定值。
  235. end
  236. local state, next = #c, nil -- 当前起始状态为缓存数组的最末项索引(或数组长度)。
  237. while index > #c do
  238. state, next = iqenum(iq, state)
  239. if next == nil then break end
  240. next = { func(state, unpack(next)) } -- 调用选择函数。
  241. table.insert(c, next) -- 向缓存数组中插入新项。
  242. end
  243. if next == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  244. end
  245. mt.__enum = __enum
  246. mt.__reset = function(q)
  247. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  248. if __reset then __reset(query) end -- 首先重置内部查询对象。
  249. local self = getmetatable(q)
  250. self.__cache = {}
  251. self.__cachedone = false
  252. iqenum, iq = nil, nil
  253. end
  254. mt.__ipairs = __ipairs
  255. mt.__pairs = __pairs
  256. local qResult = {}
  257. luaq.util.attachLuaq(qResult, mt)
  258. return qResult
  259. end
  260. function luaq.selectMany(query, func)
  261. if type(query) == "table" then
  262. if not isQuery(query) then
  263. query = luaq.iasQuery(query)
  264. end
  265. else
  266. luaq.util.errBadArgValue("selectMany", 1, "查询对象", t, "(不是%s)。")
  267. end
  268. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("selectMany", 2, "nil或function", func) end
  269. local iqenum, iq, iqstate -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  270. local tqenum, tq, tqstate -- 临时查询对象的枚举元函数、固定值以及迭代器的起始状态。
  271. local mt = {
  272. __cache = {},
  273. __cachedone = false
  274. }
  275. mt.__index = __index
  276. mt.__cachetill = function(self, index)
  277. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  278. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  279. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  280. local c = self.__cache -- 获取缓存数组。
  281. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  282. if iqenum == nil then
  283. iqenum, iq, iqstate = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  284. iqstate, tq = iqenum(iq, iqstate)
  285. end
  286. local next
  287. while index > #c do
  288. if tq == nil then break end
  289. if tqenum == nil then
  290. if func == nil then
  291. tq = unpack(tq) -- 拆包,获取元组第一个项目,进行下一步处理。
  292. else
  293. tq = { func(iqstate, unpack(tq)) }
  294. end
  295. if type(tq) == "table" then
  296. if not isQuery(tq) then
  297. tq = luaq.iasQuery(tq)
  298. end
  299. else
  300. error(mw.ustring.format("处理序列中的第%d项时发生错误(不是查询对象)。", iqstate))
  301. end
  302. tqenum, tqstate = getmetatable(tq).__enum, 0 -- 获取临时查询对象的枚举元函数以及迭代器的起始状态。
  303. end
  304. tqstate, next = tqenum(tq, tqstate)
  305. if next == nil then
  306. iqstate, tq = iqenum(iq, iqstate) -- 获取内部查询对象的枚举元函数以及迭代器的起始状态。
  307. tqenum, tqstate = nil, nil
  308. else
  309. table.insert(c, next) -- 向缓存数组中插入新项。
  310. end
  311. end
  312. if tq == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  313. end
  314. mt.__enum = __enum
  315. mt.__reset = function(q)
  316. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  317. if __reset then __reset(query) end -- 首先重置内部查询对象。
  318. local self = getmetatable(q)
  319. self.__cache = {}
  320. self.__cachedone = false
  321. iqenum, iq, iqstate = nil, nil, nil
  322. tqenum, tq, tqstate = nil, nil, nil
  323. end
  324. mt.__ipairs = __ipairs
  325. mt.__pairs = __pairs
  326. local qResult = {}
  327. luaq.util.attachLuaq(qResult, mt)
  328. return qResult
  329. end
  330. function luaq.selectYield(query, func)
  331. if type(query) == "table" then
  332. if not isQuery(query) then
  333. query = luaq.iasQuery(query)
  334. end
  335. else
  336. luaq.util.errBadArgValue("select", 1, "查询对象", query, "(不是%s)。")
  337. end
  338. if type(func) ~= "function" then luaq.util.errBadArgType("select", 2, "function", func) end
  339. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  340. local mt = {
  341. __cache = {},
  342. __cachedone = false
  343. }
  344. local yield = function(...) table.insert(mt.__cache, { ... }) end -- 迭代器产出函数。
  345. mt.__index = __index
  346. mt.__cachetill = function(self, index)
  347. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  348. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  349. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  350. local c = self.__cache -- 获取缓存数组。
  351. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  352. if iqenum == nil then
  353. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  354. end
  355. local next
  356. while index > #c do
  357. state, next = iqenum(iq, state)
  358. if next == nil then break end
  359. func(yield, state, unpack(next)) -- 调用迭代函数。
  360. end
  361. if next == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  362. end
  363. mt.__enum = __enum
  364. mt.__reset = function(q)
  365. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  366. if __reset then __reset(query) end -- 首先重置内部查询对象。
  367. local self = getmetatable(q)
  368. self.__cache = {}
  369. self.__cachedone = false
  370. iqenum, iq, state = nil, nil, nil
  371. end
  372. mt.__ipairs = __ipairs
  373. mt.__pairs = __pairs
  374. local qResult = {}
  375. luaq.util.attachLuaq(qResult, mt)
  376. return qResult
  377. end
  378. function luaq.where(query, func)
  379. if type(query) == "table" then
  380. if not isQuery(query) then
  381. query = luaq.iasQuery(query)
  382. end
  383. else
  384. luaq.util.errBadArgValue("where", 1, "查询对象", query, "(不是%s)。")
  385. end
  386. if type(func) ~= "function" then luaq.util.errBadArgType("where", 2, "function", func) end
  387. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  388. local mt = {
  389. __cache = {},
  390. __cachedone = false
  391. }
  392. mt.__index = __index
  393. mt.__cachetill = function(self, index)
  394. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  395. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  396. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  397. local c = self.__cache -- 获取缓存数组。
  398. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  399. if iqenum == nil then
  400. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  401. end
  402. local next = nil
  403. while index > #c do
  404. state, next = iqenum(iq, state)
  405. if next == nil then break end
  406. if func(state, unpack(next)) then -- 调用筛选函数。
  407. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  408. end
  409. end
  410. if next == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  411. end
  412. mt.__enum = __enum
  413. mt.__reset = function(q)
  414. local __reset = getmetatable(query).__reset
  415. if __reset then __reset(query) end -- 首先重置内部查询对象。
  416. local self = getmetatable(q)
  417. self.__cache = {}
  418. self.__cachedone = false
  419. iqenum, iq, state = nil, nil, nil
  420. end
  421. mt.__ipairs =__ipairs
  422. mt.__pairs = __pairs
  423. local qResult = {}
  424. luaq.util.attachLuaq(qResult, mt)
  425. return qResult
  426. end
  427. -- 创建一个空的查询对象。
  428. function luaq.empty()
  429. local mt = {}
  430. mt.__enum = function(q, index) return nil end
  431. mt.__reset = nil
  432. mt.__ipairs = __ipairs
  433. mt.__pairs = __pairs
  434. local qResult = {}
  435. luaq.util.attachLuaq(qResult, mt)
  436. return qResult
  437. end
  438. -- 获取一个查询对象的结果的项个数。
  439. function luaq.count(query)
  440. if type(query) == "table" then
  441. if not isQuery(query) then
  442. query = luaq.iasQuery(query)
  443. end
  444. else
  445. luaq.util.errBadArgValue("count", 1, "查询对象", t, "(不是%s)。")
  446. end
  447. local count = 0
  448. for _ in enum(query) do
  449. count = count + 1
  450. end
  451. return count
  452. end
  453. function luaq.any(query, func)
  454. if type(query) == "table" then
  455. if not isQuery(query) then
  456. query = luaq.iasQuery(query)
  457. end
  458. else
  459. luaq.util.errBadArgValue("any", 1, "查询对象", t, "(不是%s)。")
  460. end
  461. local qenum = getmetatable(query).__enum -- 获取枚举元函数。
  462. if type(func) == "nil" then
  463. local _, v = qenum(query, 0)
  464. return v ~= nil
  465. elseif type(func) ~= "function" then
  466. luaq.util.errBadArgType("any", 2, "function", func)
  467. end
  468. local i, v = qenum(query, 0)
  469. while v ~= nil do
  470. if func(unpack(v)) then return true end
  471. i, v = qenum(query, i)
  472. end
  473. return false
  474. end
  475. function luaq.all(query, func)
  476. if type(query) == "table" then
  477. if not isQuery(query) then
  478. query = luaq.iasQuery(query)
  479. end
  480. else
  481. luaq.util.errBadArgValue("all", 1, "查询对象", t, "(不是%s)。")
  482. end
  483. if type(func) ~= "function" then
  484. luaq.util.errBadArgType("all", 2, "function", func)
  485. end
  486. local qenum = getmetatable(query).__enum -- 获取枚举元函数。
  487. local i, v = qenum(query, 0)
  488. while v ~= nil do
  489. if not func(unpack(v)) then return false end
  490. i, v = qenum(query, i)
  491. end
  492. return true
  493. end
  494. function luaq.groupBy(query, keySelectFunc, entrySelectFunc, keyEqualityFunc)
  495. if type(query) == "table" then
  496. if not isQuery(query) then
  497. query = luaq.iasQuery(query)
  498. end
  499. else
  500. luaq.util.errBadArgValue("groupBy", 1, "查询对象", query, "(不是%s)。")
  501. end
  502. if type(keySelectFunc) ~= "function" then luaq.util.errBadArgType("groupBy", 2, "function", keySelectFunc) end
  503. if entrySelectFunc ~= nil and type(entrySelectFunc) ~= "function" then
  504. luaq.util.errBadArgType("groupBy", 3, "nil或function", entrySelectFunc)
  505. end
  506. if keyEqualityFunc ~= nil and type(keyEqualityFunc) ~= "function" then
  507. luaq.util.errBadArgType("groupBy", 4, "nil或function", keyEqualityFunc)
  508. end
  509. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  510. local mapcache = { -- 缓存所有项到键数组索引的映射。
  511. keys = {}, -- 储存所有键的数组。
  512. cachedone = false,
  513. cachenext = function(self)
  514. if self.cachedone then return end -- 如果已缓存完毕则退出。
  515. if iqenum == nil then
  516. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  517. end
  518. local next = nil
  519. state, next = iqenum(iq, state)
  520. if next == nil then
  521. self.cachedone = true -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  522. return
  523. end
  524. local knext = { keySelectFunc(state, unpack(next)) } -- 调用键选择函数。
  525. -- 遍历键数组中所有已有键,与新键进行相等比较判断是否相等。
  526. local hasKey = false
  527. for _keyindex, _key in ipairs(self.keys) do
  528. local keyTest -- 键相等检查
  529. if keyEqualityFunc == nil then
  530. keyTest = luaq.util.equal(_key, knext)
  531. else
  532. keyTest = keyEqualityFunc(_key, knext)
  533. end
  534. if keyTest then -- 找到已有的相同的键,则将当前项归组至这个键。
  535. hasKey = true
  536. table.insert(self, { _keyindex, next }) -- 缓存数组中保存指向键数组的索引+项。
  537. break
  538. end
  539. end
  540. if not hasKey then -- 未找到已有的相同的键,则创建新键以归组当前项。
  541. table.insert(self.keys, knext) -- 向键数组插入一个不同的键。
  542. table.insert(self, { #self.keys, next }) -- 向缓存数组插入指向键数组末尾的索引+项。
  543. end
  544. end,
  545. reset = function(self)
  546. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  547. if __reset then __reset(query) end -- 首先重置内部查询对象。
  548. self.keys = {} -- 重置键数组
  549. self.cachedone = false -- 重置缓存完毕标识符。
  550. local length = #self
  551. for i = 1, length do self[i] = nil end -- 清空映射缓存。
  552. iqenum, iq, state = nil, nil, nil
  553. end
  554. }
  555. local gmt = {
  556. __cache = {},
  557. __cachedone = false
  558. }
  559. gmt.__index = __index
  560. gmt.__cachetill = function(gself, gindex)
  561. if gself.__cachedone then return end -- 如果已缓存完毕则退出。
  562. if type(gindex) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", gindex) end
  563. if gindex <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", gindex) end
  564. local gc = gself.__cache -- 获取缓存数组。
  565. if gindex <= #gc then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  566. while gindex > #gc do
  567. local nextKeyIndex = #gc + 1 -- 获取下一个键的索引。
  568. local nextKey = mapcache.keys[nextKeyIndex] -- 获取下一个键。
  569. while nextKey == nil and not mapcache.cachedone do -- 获取键时映射缓存未完成。
  570. -- 重复向后缓存一个项并检查是否得到下一个键。
  571. mapcache:cachenext()
  572. nextKey = mapcache.keys[nextKeyIndex]
  573. end
  574. if nextKey == nil then
  575. gself.__cachedone = true -- 映射缓存完毕时仍未找到下一个键,仅当此时设置缓存完毕标识符。
  576. break
  577. end
  578. local nextEntryIndex = 1 -- 获取下一个项的索引。
  579. local emt= {
  580. __cache = {},
  581. __cachedone = false
  582. }
  583. emt.__index = __index
  584. emt.__cachetill = function(eself, eindex)
  585. if eself.__cachedone then return end -- 如果已缓存完毕则退出。
  586. if type(eindex) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", eindex) end
  587. if eindex <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", eindex) end
  588. local ec = eself.__cache -- 获取缓存数组。
  589. if eindex <= #ec then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  590. while eindex > #ec do
  591. local nextEntry = mapcache[nextEntryIndex] -- 获取下一个项。
  592. while (nextEntry == nil or nextEntry[1] ~= nextKeyIndex) do -- 获得的下个项不符合条件。
  593. -- 重复向后缓存一个项并检查是否得到下一个符合条件的项。
  594. if nextEntry == nil then -- 若当前索引位置未缓存,则缓存一个位置。
  595. if mapcache.cachedone then break end -- 映射缓存已完毕。
  596. mapcache:cachenext()
  597. else -- 若当前索引位置的项不符合条件,则尝试下一个索引位置。
  598. nextEntryIndex = nextEntryIndex + 1
  599. end
  600. nextEntry = mapcache[nextEntryIndex]
  601. end
  602. if nextEntry == nil then
  603. eself.__cachedone = true -- 映射缓存完毕时仍未找到下一个项,仅当此时设置缓存完毕标识符。
  604. break
  605. end
  606. local newEntry
  607. if entrySelectFunc == nil then
  608. newEntry = { nextKey, unpack(nextEntry[2]) }
  609. else
  610. newEntry = { nextKey, entrySelectFunc(eindex, mapcache.keys[nextKeyIndex], unpack(nextEntry[2])) } -- 调用项选择函数。
  611. end
  612. table.insert(ec, newEntry) -- 向缓存数组中插入新项。
  613. nextEntryIndex = nextEntryIndex + 1
  614. end
  615. end
  616. emt.__enum = __enum
  617. emt.__reset = function(q)
  618. -- 项查询对象的重置将不改变分组结果,仅重新获取项选择函数的返回值。
  619. local self = getmetatable(q)
  620. self.__cache = {}
  621. self.__cachedone = false
  622. nextEntryIndex = 1
  623. end
  624. emt.__ipairs = __ipairs
  625. emt.__pairs = __pairs
  626. local eqResult = {}
  627. luaq.util.attachLuaq(eqResult, emt)
  628. -- 将项查询对象添加入缓存。
  629. table.insert(gc, { nextKey, eqResult })
  630. end
  631. end
  632. gmt.__enum = __enum
  633. gmt.__reset = function(q)
  634. mapcache:reset() -- 首先重置映射缓存。
  635. local self = getmetatable(q)
  636. self.__cache = {}
  637. self.__cachedone = false
  638. end
  639. gmt.__ipairs = __ipairs
  640. gmt.__pairs = __pairs
  641. local gqResult = {}
  642. luaq.util.attachLuaq(gqResult, gmt)
  643. return gqResult
  644. end
  645. local function isSort(sort) return type(sort) == "table" and type(sort.start) == "function" end
  646. local function isOrderedQuery(t)
  647. return isQuery(t) and type(getmetatable(t).__group) == "function"
  648. end
  649. -- 获取默认排序器。
  650. local function getDefaultSort(stages)
  651. return {
  652. start = function(self, info, desc, ...)
  653. -- 冒泡排序。
  654. local count = info.length(...)
  655. for i = 1, count do
  656. local swaped = false
  657. for j = 1, count - i do
  658. if (info.compare(j, j + 1, ...) < 0) == desc then
  659. swaped = info.swap(j, j + 1, ...) or swaped
  660. end
  661. end
  662. if not swaped then break end
  663. end
  664. end
  665. }
  666. end
  667. function luaq.orderBy(query, func, comp, desc, sort)
  668. if type(query) == "table" then
  669. if not isQuery(query) then
  670. query = luaq.iasQuery(query)
  671. end
  672. else
  673. luaq.util.errBadArgValue("orderBy", 1, "查询对象", t, "(不是%s)。")
  674. end
  675. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("orderBy", 2, "function", func) end
  676. if comp ~= nil and type(comp) ~= "function" then luaq.util.errBadArgType("orderBy", 3, "nil或function", comp) end
  677. if desc == nil then desc = false
  678. elseif type(desc) ~= "boolean" then luaq.util.errBadArgType("orderBy", 4, "nil或boolean", desc) end
  679. if sort == nil then sort = getDefaultSort()
  680. elseif not isSort(sort) then luaq.util.errBadArgValue("orderBy", 5, "排序器", t, "(不是%s)。")
  681. end
  682. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  683. local sortcache = {} -- 缓存排序内容等信息。
  684. sortcache.cachedone = false -- 缓存完毕标识符。
  685. sortcache.cacheall = function(self)
  686. if self.cachedone then return end -- 如果已缓存完毕则退出。
  687. if iqenum == nil then
  688. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  689. end
  690. local next = nil
  691. while true do
  692. state, next = iqenum(iq, state)
  693. if next == nil then break end -- 仅当数组下一个项是nil时循环终止。
  694. local pair = {} -- 排序键值对。
  695. if func == nil then
  696. pair = { next } -- 不做排序键选择,即将自身作为排序键。
  697. else
  698. pair = { { func(state, unpack(next)) }, next } -- 调用排序键选择函数。
  699. end
  700. -- 遍历缓存中所有已有项组,与下一项进行相等比较判断是否相等。
  701. local isEven = false
  702. for _, _group in ipairs(self) do
  703. local current = _group[1][1] -- 从项组中获取当前要比较的项。
  704. local evenTest -- 项相等检查
  705. if comp == nil then
  706. evenTest = luaq.util.equal(current, pair[1])
  707. else
  708. evenTest = comp(current, pair[1]) == 0
  709. end
  710. if evenTest then -- 找到已有的相同的项组,则将当前项归组至这个组。
  711. isEven = true
  712. table.insert(_group, pair)
  713. break
  714. end
  715. end
  716. if not isEven then -- 未找到已有的相同的项组,则创建新组以归组当前项。
  717. table.insert(self, { pair })
  718. end
  719. end
  720. self.cachedone = true -- 设置缓存完毕标识符
  721. end
  722. sortcache.length = function() return #sortcache end
  723. sortcache.entryat = function(index)
  724. if type(index) ~= "number" then luaq.util.errBadArgType("entryat", 1, "number", index) end
  725. if index <= 0 then luaq.util.errBadArgValue("entryat", 1, "正整数", index) end
  726. local group = sortcache[index] -- 获取等值组。
  727. if group == nil then return nil
  728. else return group[1][1] -- 等值组的首项的选择键。
  729. end
  730. end
  731. sortcache.compare = function(index1, index2)
  732. if type(index1) ~= "number" then luaq.util.errBadArgType("compare", 1, "number", index1) end
  733. if index1 <= 0 then luaq.util.errBadArgValue("compare", 1, "正整数", index1) end
  734. if type(index2) ~= "number" then luaq.util.errBadArgType("compare", 2, "number", index2) end
  735. if index2 <= 0 then luaq.util.errBadArgValue("compare", 2, "正整数", index2) end
  736. local temp1, temp2 = sortcache[index1], sortcache[index2]
  737. if temp1 == nil and temp2 == nil then return 0 -- 两个索引均超出范围。
  738. elseif temp1 == nil then return -1 -- 第一个索引均超出范围。
  739. elseif temp2 == nil then return 1 -- 第二个索引均超出范围。
  740. else
  741. temp1, temp2 = temp1[1][1], temp2[1][1] -- 等值组的首项的选择键。
  742. if comp == nil then
  743. return luaq.util.compare(temp1, temp2)
  744. else
  745. return comp(temp1, temp2)
  746. end
  747. end
  748. end
  749. sortcache.swap = function(index1, index2)
  750. if type(index1) ~= "number" then luaq.util.errBadArgType("swap", 1, "number", index1) end
  751. if index1 <= 0 then luaq.util.errBadArgValue("swap", 1, "正整数", index1) end
  752. if type(index2) ~= "number" then luaq.util.errBadArgType("swap", 2, "number", index2) end
  753. if index2 <= 0 then luaq.util.errBadArgValue("swap", 2, "正整数", index2) end
  754. local temp1, temp2 = sortcache[index1], sortcache[index2]
  755. if temp1 == nil or temp2 == nil then return false end -- 其中任何一项索引超出范围则返回不成功。
  756. sortcache[index1], sortcache[index2] = temp2, temp1
  757. return true -- 交换操作成功。
  758. end
  759. sortcache.setall = function(indexes)
  760. if type(indexes) ~= "table" then luaq.util.errBadArgType("setall", 1, "table", indexes) end
  761. local length = #sortcache
  762. for i = 1, length do indexes[i] = sortcache[indexes[i]] end
  763. for i = 1, length do sortcache[i] = indexes[i] end
  764. end
  765. sortcache.sortdone = false -- 排序完毕标识符。
  766. sortcache.sort = function(self)
  767. if self.sortdone then return end
  768. self:cacheall() -- 缓存所有项。
  769. assert(self.cachedone, "排序缓存未缓存完毕,无法进行排序。") -- 设置断言捕捉潜在的逻辑错误。排序操作必须在缓存完毕的基础上进行,否则将会产生无法预料的后果。
  770. sort:start(self, desc) -- 调用排序器。
  771. self.sortdone = true
  772. end
  773. sortcache.reset = function(self)
  774. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  775. if __reset then __reset(query) end -- 首先重置内部查询对象。
  776. self.cachedone = false -- 重置缓存完毕标识符。
  777. self.sortdone = false -- 重置排序完毕标识符。
  778. local length = #self
  779. for i = 1, length do self[i] = nil end -- 清空排序缓存。
  780. iqenum, iq, state = nil, nil, 0
  781. end
  782. local mt = {
  783. __cache = {},
  784. __cachedone = false
  785. }
  786. mt.__index = __index
  787. mt.__cachetill = function(self, index)
  788. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  789. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  790. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  791. local c = self.__cache -- 获取缓存数组。
  792. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  793. sortcache:sort() -- 排序所有项。
  794. assert(sortcache.sortdone, "排序缓存未排序完毕,无法进行结果缓存。") -- 设置断言捕捉潜在的逻辑错误。结果缓存操作必须在排序完毕的基础上进行,否则将会产生无法预料的后果。
  795. -- 缓存所有结果。
  796. for _, group in ipairs(sortcache) do
  797. for _, entry in ipairs(group) do
  798. table.insert(c, entry[2] or entry[1])
  799. end
  800. end
  801. self.__cachedone = true -- 设置缓存完毕标识符。
  802. end
  803. mt.__group = function(q, index)
  804. sortcache:sort() -- 排序所有项。
  805. assert(sortcache.sortdone, "排序缓存未排序完毕,无法进行排序组枚举。") -- 设置断言捕捉潜在的逻辑错误。排序组枚举操作必须在排序完毕的基础上进行,否则将会产生无法预料的后果。
  806. index = index + 1
  807. local current = sortcache[index]
  808. if current then
  809. local group = {}
  810. for _, current in ipairs(current) do
  811. table.insert(group, current[2] or current[1])
  812. end
  813. assert(#group > 0, "空的等值组。") -- 不应出现空的等值组。
  814. return index, group
  815. end
  816. end
  817. mt.__enum = __enum
  818. mt.__reset = function(q)
  819. sortcache:reset() -- 首先重置排序缓存。
  820. local self = getmetatable(q)
  821. self.__cache = {}
  822. self.__cachedone = false
  823. end
  824. mt.__ipairs = __ipairs
  825. mt.__pairs = __pairs
  826. local qResult = {}
  827. luaq.util.attachLuaq(qResult, mt)
  828. return qResult
  829. end
  830. function luaq.thenBy(query, func, comp, desc, sort)
  831. if not isOrderedQuery(query) then
  832. luaq.util.errBadArgValue("thenBy", 1, "有序查询对象", t, "(不是%s)。")
  833. end
  834. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("thenBy", 2, "function", func) end
  835. if comp ~= nil and type(comp) ~= "function" then luaq.util.errBadArgType("thenBy", 3, "nil或function", comp) end
  836. if desc == nil then desc = false
  837. elseif type(desc) ~= "boolean" then luaq.util.errBadArgType("thenBy", 4, "nil或boolean", desc) end
  838. if sort == nil then sort = getDefaultSort()
  839. elseif not isSort(sort) then luaq.util.errBadArgValue("thenBy", 5, "排序器", t, "(不是%s)。")
  840. end
  841. local iqgroup, iq, state -- 内部查询对象的排序组元函数、固定值以及迭代器的起始状态。
  842. local totalState = 0 -- 整体状态。
  843. local sortcache = {} -- 缓存排序内容等信息。
  844. sortcache.cachedone = false
  845. sortcache.cachenext = function(self)
  846. if self.cachedone then return false end -- 如果已缓存完毕则退出。
  847. if iqgroup == nil then
  848. iqgroup, iq, state = getmetatable(query).__group, query, 0 -- 获取内部查询对象的排序组元函数、固定值以及迭代器的起始状态。
  849. end
  850. local nextStage = nil
  851. state, nextStage = iqgroup(iq, state)
  852. if nextStage == nil then
  853. self.cachedone = true -- 仅当排序组下一个项是nil时设置缓存完毕标识符。
  854. return false
  855. end
  856. local stage = {} -- 新建高阶排序阶。
  857. for _, next in ipairs(nextStage) do
  858. local pair = {} -- 排序键值对。
  859. if func == nil then
  860. pair = { next } -- 不做排序键选择,即将自身作为排序键。
  861. else
  862. pair = { { func(totalState + state, unpack(next)) }, next } -- 调用排序键选择函数。
  863. end
  864. -- 遍历新排序阶中所有已有项组,与下一项进行相等比较判断是否相等。
  865. local isEven = false
  866. for _, _group in ipairs(stage) do
  867. local current = _group[1][1] -- 从项组中获取当前要比较的项。
  868. local evenTest -- 项相等检查
  869. if comp == nil then
  870. evenTest = luaq.util.equal(current, pair[1])
  871. else
  872. evenTest = comp(current, pair[1]) == 0
  873. end
  874. if evenTest then -- 找到已有的相同的项组,则将当前项归组至这个组。
  875. isEven = true
  876. table.insert(_group, pair)
  877. break
  878. end
  879. end
  880. if not isEven then -- 未找到已有的相同的项组,则创建新组以归组当前项。
  881. table.insert(stage, { pair })
  882. end
  883. end
  884. table.insert(self, stage) -- 向排序缓存中添加新排序阶。
  885. return true
  886. end
  887. sortcache.length = function(stage)
  888. if type(stage) == "number" then
  889. local s = sortcache[stage]
  890. if s == nil then return nil -- 索引超出范围。
  891. else return #s -- 返回当前排序阶的长度。
  892. end
  893. else -- 返回总长度。
  894. local len = 0
  895. for _, s in sortcache do
  896. len = len + #s
  897. end
  898. return len
  899. end
  900. end
  901. sortcache.entryat = function(index, stage)
  902. if type(index) ~= "number" then luaq.util.errBadArgType("entryat", 1, "number", index) end
  903. if index <= 0 then luaq.util.errBadArgValue("entryat", 1, "正整数", index) end
  904. if type(stage) ~= "number" then luaq.util.errBadArgType("entryat", 2, "number", stage) end
  905. if stage <= 0 then luaq.util.errBadArgValue("entryat", 2, "正整数", stage) end
  906. stage = sortcache[stage] -- 获取排序阶。
  907. if stage == nil then return nil end -- 索引超出范围。
  908. local group = stage[index] -- 获取等值组。
  909. if group == nil then return nil
  910. else return group[1][1] -- 等值组的首项的选择键。
  911. end
  912. end
  913. sortcache.compare = function(index1, index2, stage)
  914. if type(index1) ~= "number" then luaq.util.errBadArgType("compare", 1, "number", index1) end
  915. if index1 <= 0 then luaq.util.errBadArgValue("compare", 1, "正整数", index1) end
  916. if type(index2) ~= "number" then luaq.util.errBadArgType("compare", 2, "number", index2) end
  917. if index2 <= 0 then luaq.util.errBadArgValue("compare", 2, "正整数", index2) end
  918. if type(stage) ~= "number" then luaq.util.errBadArgType("compare", 3, "number", stage) end
  919. if stage <= 0 then luaq.util.errBadArgValue("compare", 3, "正整数", stage) end
  920. stage = sortcache[stage] -- 获取排序阶。
  921. if stage == nil then return 0 end -- 索引超出范围。
  922. local temp1, temp2 = stage[index1], stage[index2]
  923. if temp1 == nil and temp2 == nil then return 0 -- 两个索引均超出范围。
  924. elseif temp1 == nil then return -1 -- 第一个索引均超出范围。
  925. elseif temp2 == nil then return 1 -- 第二个索引均超出范围。
  926. else
  927. temp1, temp2 = temp1[1][1], temp2[1][1] -- 等值组的首项的选择键。
  928. if comp == nil then
  929. return luaq.util.compare(temp1, temp2)
  930. else
  931. return comp(temp1, temp2)
  932. end
  933. end
  934. end
  935. sortcache.swap = function(index1, index2, stage)
  936. if type(index1) ~= "number" then luaq.util.errBadArgType("swap", 1, "number", index1) end
  937. if index1 <= 0 then luaq.util.errBadArgValue("swap", 1, "正整数", index1) end
  938. if type(index2) ~= "number" then luaq.util.errBadArgType("swap", 2, "number", index2) end
  939. if index2 <= 0 then luaq.util.errBadArgValue("swap", 2, "正整数", index2) end
  940. if type(stage) ~= "number" then luaq.util.errBadArgType("swap", 3, "number", stage) end
  941. if stage <= 0 then luaq.util.errBadArgValue("swap", 3, "正整数", stage) end
  942. stage = sortcache[stage] -- 获取排序阶。
  943. if stage == nil then return false end -- 索引超出范围。
  944. local temp1, temp2 = stage[index1], stage[index2]
  945. if temp1 == nil or temp2 == nil then return false end -- 其中任何一项索引超出范围则返回不成功。
  946. stage[index1], stage[index2] = temp2, temp1
  947. return true -- 交换操作成功。
  948. end
  949. sortcache.setall = function(indexes, stage)
  950. if type(indexes) ~= "table" then luaq.util.errBadArgType("setall", 1, "table", indexes) end
  951. stage = sortcache[stage] -- 获取排序阶。
  952. if stage == nil then return end -- 索引超出范围。
  953. local length = #stage
  954. for i = 1, length do indexes[i] = stage[indexes[i]] end
  955. for i = 1, length do stage[i] = indexes[i] end
  956. end
  957. sortcache.sortdone = false
  958. sortcache.sortnext = function(self)
  959. if self.sortdone then return false end
  960. local hasNext = self:cachenext() -- 缓存下一阶。
  961. if not hasNext then
  962. self.sortdone = true
  963. return false
  964. end
  965. local stage = #self -- 获取下一阶的索引。
  966. sort:start(self, desc, stage)
  967. return true
  968. end
  969. sortcache.reset = function(self)
  970. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  971. if __reset then __reset(query) end -- 首先重置内部查询对象。
  972. self.cachedone = false -- 重置缓存完毕标识符。
  973. self.sortdone = false -- 重置排序完毕标识符。
  974. local length = #self
  975. for i = 1, length do self[i] = nil end -- 清空映射缓存。
  976. iqgroup, iq, state = nil, nil, 0
  977. end
  978. local mt = {
  979. __cache = {},
  980. __cachedone = false
  981. }
  982. mt.__index = __index
  983. mt.__cachetill = function(self, index)
  984. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  985. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  986. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  987. local c = self.__cache -- 获取缓存数组。
  988. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  989. while index > #c and not sortcache.sortdone do
  990. if not sortcache:sortnext() then break end -- 排序下一阶。
  991. local stage = sortcache[#sortcache] -- 获取下一阶。
  992. -- 缓存下一阶的所有结果。
  993. for _, group in ipairs(stage) do
  994. for _, entry in ipairs(group) do
  995. table.insert(c, entry[2] or entry[1])
  996. end
  997. end
  998. end
  999. if sortcache.sortdone then self.__cachedone = true end -- 仅当排序缓存的所有阶均排序完毕时设置缓存完毕标识符。
  1000. end
  1001. mt.__group = function(q, index)
  1002. index = index + 1
  1003. local current = nil
  1004. local offset, stage = 0, 1
  1005. while true do
  1006. local s = sortcache[stage]
  1007. if s == nil then
  1008. -- 排序下一阶。
  1009. if not sortcache:sortnext() then break end
  1010. s = sortcache[stage]
  1011. if s == nil then break end
  1012. end
  1013. if index <= offset + #s then
  1014. current = s[index - offset]
  1015. break
  1016. end
  1017. offset = offset + #s
  1018. stage = stage + 1
  1019. end
  1020. if current then
  1021. local group = {}
  1022. for _, current in ipairs(current) do
  1023. table.insert(group, current[2] or current[1])
  1024. end
  1025. assert(#group > 0, "空的等值组。") -- 不应出现空的等值组。
  1026. return index, group
  1027. end
  1028. end
  1029. mt.__enum = __enum
  1030. mt.__reset = function(q)
  1031. sortcache:reset() -- 首先重置排序缓存。
  1032. local self = getmetatable(q)
  1033. self.__cache = {}
  1034. self.__cachedone = false
  1035. end
  1036. mt.__ipairs = __ipairs
  1037. mt.__pairs = __pairs
  1038. local qResult = {}
  1039. luaq.util.attachLuaq(qResult, mt)
  1040. return qResult
  1041. end
  1042. function luaq.distinct(query, func)
  1043. if type(query) == "table" then
  1044. if not isQuery(query) then
  1045. query = luaq.iasQuery(query)
  1046. end
  1047. else
  1048. luaq.util.errBadArgValue("distinct", 1, "查询对象", query, "(不是%s)。")
  1049. end
  1050. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("distinct", 2, "nil或function", func) end
  1051. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1052. local mt = {
  1053. __cache = {},
  1054. __cachedone = false
  1055. }
  1056. mt.__index = __index
  1057. mt.__cachetill = function(self, index)
  1058. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1059. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  1060. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  1061. local c = self.__cache -- 获取缓存数组。
  1062. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  1063. if iqenum == nil then
  1064. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1065. end
  1066. local next = nil
  1067. while index > #c do
  1068. state, next = iqenum(iq, state)
  1069. if next == nil then break end
  1070. local isEven
  1071. for _, current in ipairs(c) do
  1072. if func then
  1073. local evenTest = func(current, next) -- 调用筛选函数。
  1074. isEven = evenTest == true or evenTest == 0
  1075. else
  1076. isEven = luaq.util.equal(current, next)
  1077. end
  1078. if isEven then break end
  1079. end
  1080. if not isEven then
  1081. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  1082. end
  1083. end
  1084. if next == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  1085. end
  1086. mt.__enum = __enum
  1087. mt.__reset = function(q)
  1088. local __reset = getmetatable(query).__reset
  1089. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1090. local self = getmetatable(q)
  1091. self.__cache = {}
  1092. self.__cachedone = false
  1093. iqenum, iq, state = nil, nil, nil
  1094. end
  1095. mt.__ipairs =__ipairs
  1096. mt.__pairs = __pairs
  1097. local qResult = {}
  1098. luaq.util.attachLuaq(qResult, mt)
  1099. return qResult
  1100. end
  1101. function luaq.concat(query, other)
  1102. if type(query) == "table" then
  1103. if not isQuery(query) then
  1104. query = luaq.iasQuery(query)
  1105. end
  1106. else
  1107. luaq.util.errBadArgValue("concat", 1, "查询对象", query, "(不是%s)。")
  1108. end
  1109. if type(other) == "table" then
  1110. if not isQuery(other) then
  1111. other = luaq.iasQuery(other)
  1112. end
  1113. else
  1114. luaq.util.errBadArgValue("concat", 2, "查询对象", other, "(不是%s)。")
  1115. end
  1116. local iqenum1, iqenum2 -- 两个查询对象的枚举元函数。
  1117. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1118. local mt = {
  1119. __cache = {},
  1120. __cachedone = false
  1121. }
  1122. mt.__index = __index
  1123. mt.__cachetill = function(self, index)
  1124. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1125. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  1126. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  1127. local c = self.__cache -- 获取缓存数组。
  1128. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  1129. iqenum1 = iqenum1 or getmetatable(query).__enum
  1130. iqenum2 = iqenum2 or getmetatable(other).__enum
  1131. if iqenum == nil then
  1132. iqenum, iq, state = iqenum1, query, 0 -- 获取第一个内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1133. end
  1134. local next
  1135. while index > #c do
  1136. state, next = iqenum(iq, state)
  1137. local continue = false
  1138. if next == nil then
  1139. if iqenum == iqenum2 then break
  1140. else
  1141. iqenum, iq, state = iqenum2, other, 0 -- 获取第二个内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1142. continue = true
  1143. end
  1144. end
  1145. if not continue then
  1146. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  1147. end
  1148. end
  1149. if next == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  1150. end
  1151. mt.__enum = __enum
  1152. mt.__reset = function(q)
  1153. local __reset = getmetatable(query).__reset -- 获取第一个内部查询对象的重置元函数。
  1154. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1155. __reset = getmetatable(other).__reset -- 获取第二个内部查询对象的重置元函数。
  1156. if __reset then __reset(other) end -- 首先重置内部查询对象。
  1157. local self = getmetatable(q)
  1158. self.__cache = {}
  1159. self.__cachedone = false
  1160. iqenum, iq, state = nil, nil, nil
  1161. end
  1162. mt.__ipairs = __ipairs
  1163. mt.__pairs = __pairs
  1164. local qResult = {}
  1165. luaq.util.attachLuaq(qResult, mt)
  1166. return qResult
  1167. end
  1168. function luaq.append(query, ...)
  1169. if type(query) == "table" then
  1170. if not isQuery(query) then
  1171. query = luaq.iasQuery(query)
  1172. end
  1173. else
  1174. luaq.util.errBadArgValue("append", 1, "查询对象", query, "(不是%s)。")
  1175. end
  1176. if type(func) ~= "function" then luaq.util.errBadArgType("append", 2, "function", func) end
  1177. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1178. local extra = { ... } -- 要追加的项。
  1179. local mt = {
  1180. __cache = {},
  1181. __cachedone = false
  1182. }
  1183. mt.__index = __index
  1184. mt.__cachetill = function(self, index)
  1185. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1186. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  1187. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  1188. local c = self.__cache -- 获取缓存数组。
  1189. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  1190. if iqenum == nil then
  1191. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1192. end
  1193. local next
  1194. while index > #c do
  1195. state, next = iqenum(iq, state)
  1196. if next == nil then break end
  1197. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  1198. end
  1199. if next == nil then -- 当数组下一个项是nil时。
  1200. table.insert(c, extra) -- 向缓存数组中插入追加项。
  1201. self.__cachedone = true -- 设置缓存完毕标识符
  1202. end
  1203. end
  1204. mt.__enum = __enum
  1205. mt.__reset = function(q)
  1206. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  1207. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1208. local self = getmetatable(q)
  1209. self.__cache = {}
  1210. self.__cachedone = false
  1211. iqenum, iq, state = nil, nil, nil
  1212. end
  1213. mt.__ipairs = __ipairs
  1214. mt.__pairs = __pairs
  1215. local qResult = {}
  1216. luaq.util.attachLuaq(qResult, mt)
  1217. return qResult
  1218. end
  1219. function luaq.prepend(query, ...)
  1220. if type(query) == "table" then
  1221. if not isQuery(query) then
  1222. query = luaq.iasQuery(query)
  1223. end
  1224. else
  1225. luaq.util.errBadArgValue("prepend", 1, "查询对象", query, "(不是%s)。")
  1226. end
  1227. if type(func) ~= "function" then luaq.util.errBadArgType("prepend", 2, "function", func) end
  1228. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1229. local extra = { ... } -- 要追加的项。
  1230. local mt = {
  1231. __cache = {},
  1232. __cachedone = false
  1233. }
  1234. mt.__index = __index
  1235. mt.__cachetill = function(self, index)
  1236. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1237. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  1238. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  1239. local c = self.__cache -- 获取缓存数组。
  1240. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  1241. if iqenum == nil then
  1242. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1243. table.insert(c, extra) -- 向缓存数组中插入追加项。
  1244. end
  1245. local next
  1246. while index > #c do
  1247. state, next = iqenum(iq, state)
  1248. if next == nil then break end
  1249. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  1250. end
  1251. if next == nil then self.__cachedone = true end -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  1252. end
  1253. mt.__enum = __enum
  1254. mt.__reset = function(q)
  1255. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  1256. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1257. local self = getmetatable(q)
  1258. self.__cache = {}
  1259. self.__cachedone = false
  1260. iqenum, iq, state = nil, nil, nil
  1261. end
  1262. mt.__ipairs = __ipairs
  1263. mt.__pairs = __pairs
  1264. local qResult = {}
  1265. luaq.util.attachLuaq(qResult, mt)
  1266. return qResult
  1267. end
  1268. function luaq.reverse(query)
  1269. if type(query) == "table" then
  1270. if not isQuery(query) then
  1271. query = luaq.iasQuery(query)
  1272. end
  1273. else
  1274. luaq.util.errBadArgValue("reverse", 1, "查询对象", query, "(不是%s)。")
  1275. end
  1276. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1277. local mt = {
  1278. __cache = {},
  1279. __cachedone = false
  1280. }
  1281. mt.__index = function(q, k)
  1282. if type(k) == "number" and k > 0 then
  1283. local self = getmetatable(q)
  1284. self:__cacheall() -- 计算所有查询结果并缓存。
  1285. return self.__cache[#self.__cache - k + 1]
  1286. end
  1287. end
  1288. mt.__cacheall = function(self)
  1289. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1290. if iqenum == nil then
  1291. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1292. end
  1293. local c = self.__cache -- 获取缓存数组。
  1294. local next
  1295. while true do
  1296. state, next = iqenum(iq, state)
  1297. if next == nil then break end
  1298. table.insert(c, next) -- 向缓存数组中插入新项。
  1299. end
  1300. self.__cachedone = true -- 设置缓存完毕标识符。
  1301. end
  1302. mt.__enum = __enum
  1303. mt.__reset = function(q)
  1304. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  1305. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1306. local self = getmetatable(q)
  1307. self.__cache = {}
  1308. self.__cachedone = false
  1309. iqenum, iq, state = nil, nil, nil
  1310. end
  1311. mt.__ipairs = __ipairs
  1312. mt.__pairs = __pairs
  1313. local qResult = {}
  1314. luaq.util.attachLuaq(qResult, mt)
  1315. return qResult
  1316. end
  1317. function luaq.aggregate(query, func, seed, ...)
  1318. if type(query) == "table" then
  1319. if not isQuery(query) then
  1320. query = luaq.iasQuery(query)
  1321. end
  1322. else
  1323. luaq.util.errBadArgValue("aggregate", 1, "查询对象", query, "(不是%s)。")
  1324. end
  1325. if type(func) ~= "function" then luaq.util.errBadArgType("aggregate", 2, "function", func) end
  1326. if seed ~= nil or type(seed) ~= "table" then luaq.util.errBadArgValue("aggregate", 2, "合法的元组", query, "(不是%s)。") end
  1327. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1328. local _, result = iqenum(iq, 0)
  1329. local result, next = seed, nil
  1330. while true do
  1331. state, next = iqenum(iq, state)
  1332. if next == nil then break end
  1333. if result then
  1334. result = { func(state - 1, result, state, next) }
  1335. else result = next
  1336. end
  1337. end
  1338. if result == nil then return ...
  1339. else return unpack(result)
  1340. end
  1341. end
  1342. function luaq.reserve(query, ...)
  1343. if type(query) == "table" then
  1344. if not isQuery(query) then
  1345. query = luaq.iasQuery(query)
  1346. end
  1347. else
  1348. luaq.util.errBadArgValue("reserve", 1, "查询对象", query, "(不是%s)。")
  1349. end
  1350. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1351. local default = { ... } -- 要预留的项。
  1352. local mt = {
  1353. __cache = {},
  1354. __cachedone = false
  1355. }
  1356. mt.__index = __index
  1357. mt.__cachetill = function(self, index)
  1358. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1359. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  1360. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  1361. local c = self.__cache -- 获取缓存数组。
  1362. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  1363. if iqenum == nil then
  1364. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1365. end
  1366. local next
  1367. while index > #c do
  1368. state, next = iqenum(iq, state)
  1369. if next == nil then break end
  1370. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  1371. end
  1372. if next == nil then -- 当数组下一个项是nil时。
  1373. if #c == 0 then -- 内部查询对象为空(缓存为空)
  1374. table.insert(c, extra) -- 向缓存数组中插入预留项。
  1375. end
  1376. self.__cachedone = true -- 设置缓存完毕标识符
  1377. end
  1378. end
  1379. mt.__enum = __enum
  1380. mt.__reset = function(q)
  1381. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  1382. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1383. local self = getmetatable(q)
  1384. self.__cache = {}
  1385. self.__cachedone = false
  1386. iqenum, iq, state = nil, nil, nil
  1387. end
  1388. mt.__ipairs = __ipairs
  1389. mt.__pairs = __pairs
  1390. local qResult = {}
  1391. luaq.util.attachLuaq(qResult, mt)
  1392. return qResult
  1393. end
  1394. function luaq.first(query, ...)
  1395. if type(query) == "table" then
  1396. if not isQuery(query) then
  1397. query = luaq.iasQuery(query)
  1398. end
  1399. else
  1400. luaq.util.errBadArgValue("first", 1, "查询对象", query, "(不是%s)。")
  1401. end
  1402. local iqenum, iq = getmetatable(query).__enum, query -- 获取内部查询对象的枚举元函数以及固定值。
  1403. local _, result = iqenum(iq, 0)
  1404. if result == nil then return ...
  1405. else return unpack(result)
  1406. end
  1407. end
  1408. function luaq.last(query, ...)
  1409. if type(query) == "table" then
  1410. if not isQuery(query) then
  1411. query = luaq.iasQuery(query)
  1412. end
  1413. else
  1414. luaq.util.errBadArgValue("last", 1, "查询对象", query, "(不是%s)。")
  1415. end
  1416. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1417. local result, next
  1418. while true do
  1419. state, next = iqenum(iq, state)
  1420. if next == nil then break
  1421. else result = next
  1422. end
  1423. end
  1424. if result == nil then return ...
  1425. else return unpack(result)
  1426. end
  1427. end
  1428. function luaq.only(query, ...)
  1429. if type(query) == "table" then
  1430. if not isQuery(query) then
  1431. query = luaq.iasQuery(query)
  1432. end
  1433. else
  1434. luaq.util.errBadArgValue("only", 1, "查询对象", query, "(不是%s)。")
  1435. end
  1436. local iqenum, iq = getmetatable(query).__enum, query -- 获取内部查询对象的枚举元函数以及固定值。
  1437. local state, result = iqenum(iq, 0)
  1438. if result == nil or iqenum(iq, state) ~= nil then return ... -- 仅当不存在第一项或存在第二项时返回默认值。
  1439. else return unpack(result)
  1440. end
  1441. end
  1442. function luaq.sum(query, addition, ...)
  1443. if type(query) == "table" then
  1444. if not isQuery(query) then
  1445. query = luaq.iasQuery(query)
  1446. end
  1447. else
  1448. luaq.util.errBadArgValue("sum", 1, "查询对象", query, "(不是%s)。")
  1449. end
  1450. if type(addition) ~= "nil" and type(addition) ~= "function" then luaq.util.errBadArgType("average", 2, "nil或function", addition)
  1451. end
  1452. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1453. local result, next
  1454. while true do
  1455. state, next = iqenum(iq, state)
  1456. if next == nil then break end
  1457. if result == nil then
  1458. if addition == nil then
  1459. local temp = {}
  1460. local length = select("#", next)
  1461. for _index = 1, length do
  1462. temp[_index] = tonumber(next[_index])
  1463. end
  1464. result = temp
  1465. else result = next
  1466. end
  1467. else
  1468. if addition == nil then
  1469. local temp = {}
  1470. local length = math.max(select("#", result), select("#", next))
  1471. for _index = 1, length do
  1472. local v1, v2 = result[_index], tonumber(next[_index])
  1473. if v1 ~= nil and v2 ~= nil then
  1474. temp[_index] = v1 + v2
  1475. else
  1476. temp[_index] = v1 or v2
  1477. end
  1478. end
  1479. else result = addition(result, next)
  1480. end
  1481. end
  1482. end
  1483. if result == nil then return ...
  1484. else return unpack(result)
  1485. end
  1486. end
  1487. function luaq.average(query, addition, division, ...)
  1488. if type(query) == "table" then
  1489. if not isQuery(query) then
  1490. query = luaq.iasQuery(query)
  1491. end
  1492. else
  1493. luaq.util.errBadArgValue("average", 1, "查询对象", query, "(不是%s)。")
  1494. end
  1495. if addition == nil then division = nil -- 未提供求和函数时,使用默认的求和函数及求商函数。
  1496. elseif type(addition) ~= "function" then luaq.util.errBadArgType("average", 2, "nil或function", addition)
  1497. end
  1498. if division ~= nil and type(division) ~= "function" then luaq.util.errBadArgType("average", 3, "nil或function", division) end
  1499. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1500. local result, count, next
  1501. while true do
  1502. state, next = iqenum(iq, state)
  1503. if next == nil then break end
  1504. if result == nil then
  1505. if addition == nil then
  1506. local temp = {}
  1507. local length = select("#", next)
  1508. for _index = 1, length do
  1509. temp[_index] = tonumber(next[_index])
  1510. end
  1511. result = temp
  1512. else result = next
  1513. end
  1514. else
  1515. if addition == nil then
  1516. local temp = {}
  1517. local length = math.max(select("#", result), select("#", next))
  1518. for _index = 1, length do
  1519. local v1, v2 = result[_index], tonumber(next[_index])
  1520. if v1 ~= nil and v2 ~= nil then
  1521. temp[_index] = v1 + v2
  1522. else
  1523. temp[_index] = v1 or v2
  1524. end
  1525. end
  1526. else result = addition(result, next)
  1527. end
  1528. end
  1529. count = count + 1
  1530. end
  1531. if result == nil then return ... end
  1532. if division == nil then
  1533. local length = select("#", result)
  1534. for _index = 1, length do
  1535. if result[_index] then
  1536. result[_index] = result[_index] / count
  1537. end
  1538. end
  1539. else result = division(unpack(result))
  1540. end
  1541. return unpack(result)
  1542. end
  1543. function luaq.max(query, comp, ...)
  1544. if type(query) == "table" then
  1545. if not isQuery(query) then
  1546. query = luaq.iasQuery(query)
  1547. end
  1548. else
  1549. luaq.util.errBadArgValue("max", 1, "查询对象", query, "(不是%s)。")
  1550. end
  1551. if comp ~= nil and type(comp) ~= "function" then luaq.util.errBadArgType("max", 2, "nil或function", comp) end
  1552. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1553. local result, next
  1554. while true do
  1555. state, next = iqenum(iq, state)
  1556. if next == nil then break end
  1557. if result == nil then result = next
  1558. else
  1559. if comp == nil then
  1560. if luaq.util.compare(result, next) < 0 then
  1561. result = next
  1562. end
  1563. else
  1564. local compTest = comp(result, next)
  1565. if compTest == true or compTest < 0 then
  1566. result = next
  1567. end
  1568. end
  1569. end
  1570. end
  1571. if result == nil then return ...
  1572. else return unpack(result)
  1573. end
  1574. end
  1575. function luaq.min(query, comp, ...)
  1576. if type(query) == "table" then
  1577. if not isQuery(query) then
  1578. query = luaq.iasQuery(query)
  1579. end
  1580. else
  1581. luaq.util.errBadArgValue("min", 1, "查询对象", query, "(不是%s)。")
  1582. end
  1583. if comp ~= nil and type(comp) ~= "function" then luaq.util.errBadArgType("min", 2, "nil或function", comp) end
  1584. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1585. local result, next
  1586. while true do
  1587. state, next = iqenum(iq, state)
  1588. if next == nil then break end
  1589. if result == nil then result = next
  1590. else
  1591. if comp == nil then
  1592. if luaq.util.compare(result, next) > 0 then
  1593. result = next
  1594. end
  1595. else
  1596. local compTest = comp(next, result)
  1597. if compTest == true or compTest > 0 then
  1598. result = next
  1599. end
  1600. end
  1601. end
  1602. end
  1603. if result == nil then return ...
  1604. else return unpack(result)
  1605. end
  1606. end
  1607. function luaq.sub(query, i, j)
  1608. if type(query) == "table" then
  1609. if not isQuery(query) then
  1610. query = luaq.iasQuery(query)
  1611. end
  1612. else
  1613. luaq.util.errBadArgValue("sub", 1, "查询对象", query, "(不是%s)。")
  1614. end
  1615. if type(i) ~= "number" then luaq.util.errBadArgType("sub", 2, "number", i)
  1616. elseif i > 0 then i = math.ceil(i)
  1617. elseif i < 0 then i = math.floor(i)
  1618. else luaq.util.errBadArgValue("sub", 2, "非零的整数", i)
  1619. end
  1620. if j == nil then j = -1
  1621. elseif type(j) ~= "number" then luaq.util.errBadArgType("sub", 3, "nil或number", j)
  1622. elseif j > 0 then j = math.floor(j)
  1623. elseif j < 0 then j = math.ceil(j)
  1624. else luaq.util.errBadArgValue("sub", 3, "非零的整数", j)
  1625. end
  1626. local iqenum, iq, state -- 内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1627. local buff = {}
  1628. local mt = {
  1629. __cache = {},
  1630. __cachedone = false
  1631. }
  1632. mt.__index = __index
  1633. mt.__cachetill = function(self, index)
  1634. if self.__cachedone then return end -- 如果已缓存完毕则退出。
  1635. if type(index) ~= "number" then luaq.util.errBadArgType("__cachetill", 2, "number", index) end
  1636. if index <= 0 then luaq.util.errBadArgValue("__cachetill", 2, "正整数", index) end
  1637. local c = self.__cache -- 获取缓存数组。
  1638. if index <= #c then return end -- 如果指定索引小于已缓存项的数量,则直接退出。
  1639. if iqenum == nil then
  1640. iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1641. end
  1642. if ((i < 0) == (j < 0)) and i > j then -- 两个索引符号相同且起始索引大于结束索引,截取子串为空串。
  1643. self.__cachedone = true -- 设置缓存完毕标识符。
  1644. return
  1645. end
  1646. if i < 0 then -- 当起始索引为反向定位时,必须获得内部查询对象的所有项的数量。
  1647. -- 缓存所有项。
  1648. local count = 0
  1649. while true do
  1650. local next
  1651. state, next = iqenum(iq, state)
  1652. if next == nil then break -- 缓存结束分支。
  1653. elseif j > 0 and count + i >= j then -- 计算得到起始索引大于结束索引。
  1654. self.__cachedone = true -- 设置缓存完毕标识符。
  1655. return
  1656. end
  1657. table.insert(buff, next)
  1658. count = count + 1
  1659. end
  1660. local v1, v2 = i, j
  1661. if i < 0 then v1 = count + i + 1 end -- 获得正向定位起始索引。
  1662. if j < 0 then v2 = count + j + 1 end -- 获得正向定位结束索引。
  1663. for _index = v1, v2 do
  1664. local e = buff[_index]
  1665. if e == nil then break end
  1666. table.insert(c, { unpack(e) }) -- 向缓存数组中插入新项。
  1667. end
  1668. self.__cachedone = true -- 设置缓存完毕标识符。
  1669. else
  1670. local v1, v2 = i, j
  1671. while (j < 0 or state < j) and index > #c do
  1672. local next
  1673. if j < 0 then v2 = state + j + 2 end -- 获得正向定位结束索引。
  1674. state, next = iqenum(iq, state)
  1675. if next == nil then
  1676. self.__cachedone = true -- 仅当数组下一个项是nil时设置缓存完毕标识符。
  1677. if v1 > v2 then return -- 计算得到起始索引大于结束索引。
  1678. else break
  1679. end
  1680. elseif state >= v1 then
  1681. if j > 0 then
  1682. table.insert(c, { unpack(next) }) -- 向缓存数组中插入新项。
  1683. else
  1684. table.insert(buff, next)
  1685. if v2 >= v1 then
  1686. table.insert(c, { unpack(buff[v2 - v1 + 1]) }) -- 向缓存数组中插入新项。
  1687. end
  1688. end
  1689. end
  1690. end
  1691. end
  1692. end
  1693. mt.__enum = __enum
  1694. mt.__reset = function(q)
  1695. local __reset = getmetatable(query).__reset -- 获取重置元函数。
  1696. if __reset then __reset(query) end -- 首先重置内部查询对象。
  1697. local self = getmetatable(q)
  1698. self.__cache = {}
  1699. self.__cachedone = false
  1700. iqenum, iq, state = nil, nil, nil
  1701. buff = {}
  1702. end
  1703. mt.__ipairs = __ipairs
  1704. mt.__pairs = __pairs
  1705. local qResult = {}
  1706. luaq.util.attachLuaq(qResult, mt)
  1707. return qResult
  1708. end
  1709. function luaq.skip(query, count, func)
  1710. if type(query) == "table" then
  1711. if not isQuery(query) then
  1712. query = luaq.iasQuery(query)
  1713. end
  1714. else
  1715. luaq.util.errBadArgValue("skip", 1, "查询对象", query, "(不是%s)。")
  1716. end
  1717. if type(count) ~= "number" then luaq.util.errBadArgType("skip", 2, "number", count)
  1718. elseif count < 0 then luaq.util.errBadArgValue("skip", 2, "不是自然数", count)
  1719. end
  1720. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("skip", 3, "nil或function", func) end
  1721. if func then
  1722. query = query:where(func)
  1723. end
  1724. if count >= 0 then
  1725. return query:sub(math.floor(count + 1))
  1726. else
  1727. return query:sub(1, math.ceil(count - 1))
  1728. end
  1729. end
  1730. function luaq.take(query, count, func)
  1731. if type(query) == "table" then
  1732. if not isQuery(query) then
  1733. query = luaq.iasQuery(query)
  1734. end
  1735. else
  1736. luaq.util.errBadArgValue("take", 1, "查询对象", query, "(不是%s)。")
  1737. end
  1738. if type(count) ~= "number" then luaq.util.errBadArgType("take", 2, "number", count)
  1739. elseif count < 0 then luaq.util.errBadArgValue("take", 2, "不是自然数", count)
  1740. end
  1741. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("take", 3, "nil或function", func) end
  1742. if func then
  1743. query = query:where(func)
  1744. end
  1745. if count >= 0 then
  1746. return query:sub(1, math.floor(count))
  1747. else
  1748. return query:sub(math.ceil(count))
  1749. end
  1750. end
  1751. function luaq.ofType(query, typename)
  1752. if type(query) == "table" then
  1753. if not isQuery(query) then
  1754. query = luaq.iasQuery(query)
  1755. end
  1756. else
  1757. luaq.util.errBadArgValue("ofType", 1, "查询对象", query, "(不是%s)。")
  1758. end
  1759. if type(typename) ~= "string" then luaq.util.errBadArgType("ofType", 2, "string", typename) end
  1760. return query:where(function(_, e) return type(e) == typename end)
  1761. end
  1762. function luaq.query(query)
  1763. if type(query) == "table" then
  1764. if not isQuery(query) then
  1765. query = luaq.iasQuery(query)
  1766. end
  1767. else
  1768. luaq.util.errBadArgValue("query", 1, "查询对象", query, "(不是%s)。")
  1769. end
  1770. local tResult = {}
  1771. for _, entry in enum(query) do
  1772. table.insert(tResult, entry)
  1773. end
  1774. return tResult
  1775. end
  1776. function luaq.each(query, func)
  1777. if type(query) == "table" then
  1778. if not isQuery(query) then
  1779. query = luaq.iasQuery(query)
  1780. end
  1781. else
  1782. luaq.util.errBadArgValue("foreach", 1, "查询对象", query, "(不是%s)。")
  1783. end
  1784. if type(func) ~= "function" then luaq.util.errBadArgType("foreach", 2, "function", func) end
  1785. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1786. local next
  1787. while true do
  1788. state, next = iqenum(iq, state)
  1789. if next == nil then break end
  1790. func(state, unpack(next)) -- 调用操作函数。
  1791. end
  1792. end
  1793. function luaq.has(query, func, ...)
  1794. if type(query) == "table" then
  1795. if not isQuery(query) then
  1796. query = luaq.iasQuery(query)
  1797. end
  1798. else
  1799. luaq.util.errBadArgValue("has", 1, "查询对象", query, "(不是%s)。")
  1800. end
  1801. if func ~= nil and type(func) ~= "function" then luaq.util.errBadArgType("has", 2, "nil或function", func) end
  1802. local iqenum, iq, state = getmetatable(query).__enum, query, 0 -- 获取内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1803. local entry = { ... }
  1804. local next
  1805. while true do
  1806. state, next = iqenum(iq, state)
  1807. if next == nil then break end
  1808. if func then
  1809. local evenTest = func(entry, next) -- 调用筛选函数。
  1810. if evenTest == true or evenTest == 0 then return true end -- 找到相等项。
  1811. else
  1812. if luaq.util.equal(entry, next) then return true end -- 找到相等项。
  1813. end
  1814. end
  1815. return false -- 未找到相等项。
  1816. end
  1817. function luaq.is(query, other, func, sequence)
  1818. if type(query) == "table" then
  1819. if not isQuery(query) then
  1820. query = luaq.iasQuery(query)
  1821. end
  1822. else
  1823. luaq.util.errBadArgValue("is", 1, "查询对象", query, "(不是%s)。")
  1824. end
  1825. if type(other) == "table" then
  1826. if not isQuery(other) then
  1827. other = luaq.iasQuery(other)
  1828. end
  1829. else
  1830. luaq.util.errBadArgValue("is", 2, "查询对象", other, "(不是%s)。")
  1831. end
  1832. if sequence == nil then sequence = true
  1833. elseif type(sequence) ~= "boolean" then
  1834. luaq.util.errBadArgType("is", 4, "nil或boolean", sequence)
  1835. end
  1836. if sequence then
  1837. local iqenum1, iq1, state1 = getmetatable(query).__enum, query, 0 -- 获取第一个内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1838. local iqenum2, iq2, state2 = getmetatable(other).__enum, other, 0 -- 获取另一个内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1839. local next1, next2
  1840. while true do
  1841. state1, next1 = iqenum1(iq1, state1)
  1842. state2, next2 = iqenum2(iq2, state2)
  1843. if next1 ~= nil and next2 ~= nil then
  1844. local isEven
  1845. if func then
  1846. local evenTest = func(next1, next2) -- 调用筛选函数。
  1847. isEven = evenTest == true or evenTest == 0
  1848. else
  1849. isEven = luaq.util.equal(next1, next2)
  1850. end
  1851. if not isEven then return false end
  1852. elseif (next1 == nil) ~= (next2 == nil) then return false
  1853. end
  1854. if next1 == nil or next2 == nil then break end
  1855. end
  1856. return true
  1857. else
  1858. -- 获取两个结果表,若长度不一致则不相等。
  1859. local result1 = query:distinct(func):query()
  1860. local result2 = other:distinct(func):query()
  1861. if #result1 ~= #result2 then return false end
  1862. for index1, entry1 in ipairs(result1) do
  1863. for index2, entry2 in ipairs(result2) do
  1864. if entry2 then -- 仅当entry2为table类型时才为真。(请不要轻易改动此表达式。)
  1865. local isEven
  1866. if func then
  1867. local evenTest = func(entry1, entry2) -- 调用筛选函数。
  1868. isEven = evenTest == true or evenTest == 0
  1869. else
  1870. isEven = luaq.util.equal(entry1, entry2)
  1871. end
  1872. if isEven then
  1873. result2[index2] = false -- 使得外层if条件永远为假。(请不要轻易改动此值。)
  1874. entry1 = nil -- 供外层for检测使用。(请不要轻易改动此值。)
  1875. break
  1876. end
  1877. end
  1878. end
  1879. if entry1 then return false end -- 在内层for中未被设置为nil。(请不要轻易改动此表达式。)
  1880. end
  1881. return true
  1882. end
  1883. end
  1884. local function isSubRelationship(query, other, func, sequence)
  1885. if sequence then
  1886. local iqenum1, iq1, state1 = getmetatable(query).__enum, query, 0 -- 获取第一个内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1887. local iqenum2, iq2, state2 = getmetatable(other).__enum, other, 0 -- 获取另一个内部查询对象的枚举元函数、固定值以及迭代器的起始状态。
  1888. local next1, next2
  1889. state1, next1 = iqenum1(iq1, state1)
  1890. state2, next2 = iqenum2(iq2, state2)
  1891. local fstart = false -- 序列匹配开始标识符。
  1892. while true do
  1893. if next1 == nil then return true -- 子序列匹配到结尾。
  1894. elseif next2 == nil then return false -- 子序列未匹配到结尾时,被检测序列到达结尾。
  1895. else
  1896. local isEven
  1897. if func then
  1898. local evenTest = func(next1, next2) -- 调用筛选函数。
  1899. isEven = evenTest == true or evenTest == 0
  1900. else
  1901. isEven = luaq.util.equal(next1, next2)
  1902. end
  1903. if isEven then
  1904. if not fstart then fstart = true end -- 匹配开始。
  1905. state1, next1 = iqenum1(iq1, state1) -- 子序列匹配指针向后移动一项。
  1906. else
  1907. if fstart then -- 复位子序列匹配指针以及状态。
  1908. fstart = false
  1909. state1, next1 = iqenum1(iq1, 0)
  1910. end
  1911. end
  1912. state2, next2 = iqenum2(iq2, state2) -- 被检测序列指针向后移动一项。
  1913. end
  1914. end
  1915. else
  1916. -- 获取两个结果表。
  1917. local result1 = query:distinct(func):query()
  1918. local result2 = other:query()
  1919. for index1, entry1 in ipairs(result1) do
  1920. for index2, entry2 in ipairs(result2) do
  1921. if entry2 then -- 仅当entry2为table类型时才为真。(请不要轻易改动此表达式。)
  1922. local isEven
  1923. if func then
  1924. local evenTest = func(entry1, entry2) -- 调用筛选函数。
  1925. isEven = evenTest == true or evenTest == 0
  1926. else
  1927. isEven = luaq.util.equal(entry1, entry2)
  1928. end
  1929. if isEven then
  1930. result2[index2] = false -- 使得外层if条件永远为假。(请不要轻易改动此值。)
  1931. entry1 = nil -- 供外层for检测使用。(请不要轻易改动此值。)
  1932. break
  1933. end
  1934. end
  1935. end
  1936. if entry1 then return false end -- 在内层for中未被设置为nil。(请不要轻易改动此表达式。)
  1937. end
  1938. return true
  1939. end
  1940. end
  1941. function luaq.subOf(query, other, func, sequence)
  1942. if type(query) == "table" then
  1943. if not isQuery(query) then
  1944. query = luaq.iasQuery(query)
  1945. end
  1946. else
  1947. luaq.util.errBadArgValue("subOf", 1, "查询对象", query, "(不是%s)。")
  1948. end
  1949. if type(other) == "table" then
  1950. if not isQuery(other) then
  1951. other = luaq.iasQuery(other)
  1952. end
  1953. else
  1954. luaq.util.errBadArgValue("subOf", 2, "查询对象", other, "(不是%s)。")
  1955. end
  1956. if sequence == nil then sequence = true
  1957. elseif type(sequence) ~= "boolean" then
  1958. luaq.util.errBadArgType("subOf", 4, "nil或boolean", sequence)
  1959. end
  1960. local rel = isSubRelationship(query, other, func, sequence)
  1961. return rel
  1962. end
  1963. function luaq.superOf(query, other, func, sequence)
  1964. if type(query) == "table" then
  1965. if not isQuery(query) then
  1966. query = luaq.iasQuery(query)
  1967. end
  1968. else
  1969. luaq.util.errBadArgValue("superOf", 1, "查询对象", query, "(不是%s)。")
  1970. end
  1971. if type(other) == "table" then
  1972. if not isQuery(other) then
  1973. other = luaq.iasQuery(other)
  1974. end
  1975. else
  1976. luaq.util.errBadArgValue("superOf", 2, "查询对象", other, "(不是%s)。")
  1977. end
  1978. if sequence == nil then sequence = true
  1979. elseif type(sequence) ~= "boolean" then
  1980. luaq.util.errBadArgType("superOf", 4, "nil或boolean", sequence)
  1981. end
  1982. local rel = isSubRelationship(other, query, func, sequence)
  1983. return rel
  1984. end
  1985. function luaq.properSubOf(query, other, func, sequence)
  1986. if type(query) == "table" then
  1987. if not isQuery(query) then
  1988. query = luaq.iasQuery(query)
  1989. end
  1990. else
  1991. luaq.util.errBadArgValue("properSubOf", 1, "查询对象", query, "(不是%s)。")
  1992. end
  1993. if type(other) == "table" then
  1994. if not isQuery(other) then
  1995. other = luaq.iasQuery(other)
  1996. end
  1997. else
  1998. luaq.util.errBadArgValue("properSubOf", 2, "查询对象", other, "(不是%s)。")
  1999. end
  2000. if sequence == nil then sequence = true
  2001. elseif type(sequence) ~= "boolean" then
  2002. luaq.util.errBadArgType("properSubOf", 4, "nil或boolean", sequence)
  2003. end
  2004. local rel, proper = isSubRelationship(query, other, func, sequence)
  2005. return rel and proper
  2006. end
  2007. function luaq.properSuperOf(query, other, func, sequence)
  2008. if type(query) == "table" then
  2009. if not isQuery(query) then
  2010. query = luaq.iasQuery(query)
  2011. end
  2012. else
  2013. luaq.util.errBadArgValue("properSuperOf", 1, "查询对象", query, "(不是%s)。")
  2014. end
  2015. if type(other) == "table" then
  2016. if not isQuery(other) then
  2017. other = luaq.iasQuery(other)
  2018. end
  2019. else
  2020. luaq.util.errBadArgValue("properSuperOf", 2, "查询对象", other, "(不是%s)。")
  2021. end
  2022. if sequence == nil then sequence = true
  2023. elseif type(sequence) ~= "boolean" then
  2024. luaq.util.errBadArgType("properSuperOf", 4, "nil或boolean", sequence)
  2025. end
  2026. local rel, proper = isSubRelationship(other, query, func, sequence)
  2027. return rel and proper
  2028. end
  2029. function luaq.overlap(query, other, func, sequence)
  2030. if type(query) == "table" then
  2031. if not isQuery(query) then
  2032. query = luaq.iasQuery(query)
  2033. end
  2034. else
  2035. luaq.util.errBadArgValue("overlap", 1, "查询对象", query, "(不是%s)。")
  2036. end
  2037. if type(other) == "table" then
  2038. if not isQuery(other) then
  2039. other = luaq.iasQuery(other)
  2040. end
  2041. else
  2042. luaq.util.errBadArgValue("overlap", 2, "查询对象", other, "(不是%s)。")
  2043. end
  2044. if sequence == nil then sequence = true
  2045. elseif type(sequence) ~= "boolean" then
  2046. luaq.util.errBadArgType("overlap", 4, "nil或boolean", sequence)
  2047. end
  2048. -- 获取两个结果表。
  2049. local result1 = query:distinct(func):query()
  2050. local result2 = other:distinct(func):query()
  2051. if #result1 == 0 or #result2 == 0 then return false end -- 任何一个为空集时两者不相交。
  2052. if sequence then
  2053. for i = 1, 5 do
  2054. local entry, seq
  2055. if i == 1 then entry, seq = result1[1], result2
  2056. elseif i == 2 then entry, seq = result1[#result1], result2
  2057. elseif i == 3 then entry, seq = result2[1], result1
  2058. elseif i == 4 then etnry, seq = result2[#result2], result1
  2059. else return false -- 四种情况均未发现相等项,则两者不相交。
  2060. end
  2061. for _, seqEntry in ipairs(seq) do
  2062. local isEven
  2063. if func then
  2064. local evenTest = func(entry, seqEntry) -- 调用筛选函数。
  2065. isEven = evenTest == true or evenTest == 0
  2066. else
  2067. isEven = luaq.util.equal(entry, seqEntry)
  2068. end
  2069. if isEven then return true end -- 发现相等项,两者相交。
  2070. end
  2071. end
  2072. else
  2073. for index1, entry1 in ipairs(result1) do
  2074. for index2, entry2 in ipairs(result2) do
  2075. local isEven
  2076. if func then
  2077. local evenTest = func(entry1, entry2) -- 调用筛选函数。
  2078. isEven = evenTest == true or evenTest == 0
  2079. else
  2080. isEven = luaq.util.equal(entry1, entry2)
  2081. end
  2082. if isEven then return true end -- 发现相等项,两者相交。
  2083. end
  2084. end
  2085. return false
  2086. end
  2087. end
  2088. -- 查询对象的默认链接元函数。(必须提供concat、append、prepend函数的实现。)
  2089. local function __concat(l, r)
  2090. local v1, v2 = isQuery(l), isQuery(r)
  2091. if v1 and v2 then return l:concat(r)
  2092. elseif v1 and not v2 then return l:append(r)
  2093. elseif not v1 and v2 then return l:prepend(r)
  2094. else
  2095. luaq.util.errBadArgValue("__concat", 1, "查询对象", l, "(不是%s)。")
  2096. end
  2097. end
  2098. -- 查询对象的默认乘运算元函数。(必须提供join、duplicate函数的实现。)
  2099. local function __mul(l, r)
  2100. local v1, v2 = isQuery(l), isQuery(r)
  2101. if v1 and v2 then return l:join(r)
  2102. elseif v1 and type(v2) == "number" then return l:duplicate(r)
  2103. elseif v2 and type(v1) == "number" then return r:duplicate(l)
  2104. elseif v1 then
  2105. luaq.util.errBadArgValue("__mul", 1, "查询对象", l, "(不是%s)。")
  2106. else
  2107. luaq.util.errBadArgType("__mul", 1, "number", l)
  2108. end
  2109. end
  2110. -- 查询对象的默认商运算元函数。(必须提供groupBy函数的实现。)
  2111. local function __div(query, key)
  2112. if type(query) == "table" then
  2113. if not isQuery(query) then
  2114. query = luaq.iasQuery(query)
  2115. end
  2116. else
  2117. luaq.util.errBadArgValue("__div", 1, "查询对象", query, "(不是%s)。")
  2118. end
  2119. if key == nil then luaq.util.errBadArgType("__div", 2, "非nil", key) end
  2120. local func
  2121. if type(key) == "function" then
  2122. func = key
  2123. else
  2124. func = function(_, item)
  2125. if type(item) == "table" then return item[key]
  2126. else return nil
  2127. end
  2128. end
  2129. end
  2130. query:groupBy(func)
  2131. end
  2132. -- 查询对象的默认字符串元函数。
  2133. local function __tostring(query)
  2134. if type(query) == "table" then
  2135. if not isQuery(query) then
  2136. query = luaq.iasQuery(query)
  2137. end
  2138. else
  2139. luaq.util.errBadArgValue("__tostring", 1, "查询对象", query, "(不是%s)。")
  2140. end
  2141. return mw.dumpObject(query:query())
  2142. end
  2143. function luaq.util.attachLuaq(q, mt)
  2144. q.asQuery = luaq.asQuery
  2145. q.select = luaq.select
  2146. q.selectMany = luaq.selectMany
  2147. q.selectYield = luaq.selectYield
  2148. q.where = luaq.where
  2149. q.count = luaq.count
  2150. q.any = luaq.any
  2151. q.all = luaq.all
  2152. q.groupBy = luaq.groupBy
  2153. q.orderBy = luaq.orderBy
  2154. q.thenBy = luaq.thenBy
  2155. q.distinct = luaq.distinct
  2156. q.reverse = luaq.reverse
  2157. q.concat = luaq.concat
  2158. q.append = luaq.append
  2159. q.prepend = luaq.prepend
  2160. q.aggregate = luaq.aggregate
  2161. q.reserve = luaq.reserve
  2162. q.duplicate = luaq.duplicate
  2163. --q.join = luaq.join
  2164. --q.groupJoin = luaq.groupJoin
  2165. q.first = luaq.first
  2166. q.last = luaq.last
  2167. q.only = luaq.only
  2168. q.sum = luaq.sum
  2169. q.average = luaq.average
  2170. q.max = luaq.max
  2171. q.min = luaq.min
  2172. q.sub = luaq.sub
  2173. q.skip = luaq.skip
  2174. q.take = luaq.take
  2175. q.ofType = luaq.ofType
  2176. q.query = luaq.query
  2177. q.each = luaq.each
  2178. q.has = luaq.has
  2179. --q.union = luaq.union
  2180. --q.except = luaq.except
  2181. --q.symmetricExcept = luaq.symmetricExcept
  2182. --q.intersect = luaq.intersect
  2183. --q.complement = luaq.complement
  2184. q.is = luaq.is
  2185. q.subOf = luaq.subOf
  2186. q.superOf = luaq.superOf
  2187. q.properSubOf = luaq.properSubOf
  2188. q.properSuperOf = luaq.properSuperOf
  2189. q.overlap = luaq.overlap
  2190. mt.__add = luaq.union
  2191. mt.__sub = luaq.except
  2192. mt.__mul = __mul
  2193. mt.__div = __div
  2194. mt.__unm = luaq.reverse
  2195. mt.__mod = luaq.ofType
  2196. mt.__power = luaq.join
  2197. mt.__concat = __concat
  2198. mt.__eq = luaq.is
  2199. mt.lt = luaq.properSubOf
  2200. mt.le = luaq.subOf
  2201. mt.tostring = __tostring
  2202. setmetatable(q, mt)
  2203. end
  2204. return luaq