transforms(变换)库提供了一套用于带索引表的实用工具。此运行库提供了高度可复用的特殊迭代器,这些迭代器是 text
与 sh
命令解析的核心。
所有的transform方法都预期在序列上迭代,参见https://www.lua.org/manual/5.2/manual.html#3.4.6
此API所有的 first
与 last
参数均与string
方法(例如string.sub
)中的 first
与 last
参数工作方式一致。因此可以接收负值,负值为从后向前数。first
(当选择时)默认相当于 1,而 last
默认相当于 -1。
译者注:此处的predicate通用的译名是“谓词”,指根据条件返回布尔值的函数。但译者认为这是相当糟糕的译名,不利于理解。因此译为“判断函数”。
所有接收判断函数的transform方法均使用以下定义:
predicate(element: value, index: number, tbl: table): number, number
此判断函数会在 tbl
的每个索引上依次调用。 element
为 tbl[index]
中的值。通常而言,判断函数将会忽略 index
与 tbl
,仅处理element
。但一些判断函数可能会需要检查tbl
中在index
之前或之后的值。(重要!)应注意,传递给判断函数的tbl
实际上只是传递给transform api的原始表的一个视图(view)。此处的视图(view)不是原生的序列,而是只会返回tbl
中 [first
, last
] 范围内的值。
换言之,判断函数处理一个“元素组”,并返回代表满足的条件的值。
“元素组”一词代指下列之一:
A)传递给判断函数的单个element
。与tbl[index]
的值为同一个。
或者
B)tbl
中自index
起的元素序列。判断函数可能会从index
处开始迭代,数量为其需要检查的元素数,直到 #tbl
为止。
返回值的可能情况:
参数1:若为false
或 nil
,代表元素组不满足判断函数的条件。
若为index
,代表满足条件。函数应当直接返回给定函数的索引号,也就是元素组的起始元素索引号。
参数2:满足判断函数的元素组大小,或nil
。
一些tranform方法可能会将第二个参数指定为可选,例如transforms.first()
。
一些transform方法可能会指定其他可用的判断数据类型,例如表或字符串。这些判断函数的用法特定于对应的方法,且在此处详细列出的方法中定义。
transforms.sub(tbl: table, first: number, last: number or nil): table
Behaves similarly to string.sub
. Returns a sub table of tbl
from first
to last
.
transforms.first(tbl: table, predicate: function or table, first: number or nil, last: number or nil): number, number
Returns the first index in tbl
(between indexes first
and last
, inclusively) where predicate
is satisfied. The 2nd return is also the ending index of the match. General examples will have the same two values returned, i.e. a match of length 1. The predicate
can (optionally) return a 2nd return value to indicate the size of the match.
In the case that predicate
is a table, transforms.first()
returns the starting and ending index of the first matching sub table in tbl
that matches ANY one of the tables in predicate
.
Examples:
local tx = require("transforms") print( tx.first ( { 1, 1, 3, 2, 4, 7 }, function(e, i, tbl) local evens = 0 for i=i,#tbl do if tbl[i] % 2 == 0 then evens = evens + 1 else break end end return evens > 0, evens end))
Output
4 5
local tx = require("transforms") print( tx.first ( { 1, 1, 3, 2, 4, 7 }, { {1, 2}, {3, 2, 4} }) )
Output
3 5
transforms.partition(tbl: table, partioner: function, first: number or nil, last: number or nil): table of tables
Returns a list of sub lists from tbl
, generated by partioner
within the range from first
to last
. partioner
is a predicate
function, defined above.
The index
parameter passed to the partitioner
will skip ranges, i.e. it will increase by n
where n
is the size of the partition.
The partitioner
predicate for this method must return the starting AND ending index of satisfied element sets. Again, see the predicate
info above.
transforms.begins(tbl: table, sub: table, first: number or nil, last: number or nil)
Returns true if the subset of tbl
from first
to last
fully composes v
aligned at the first index. Assuming first
and last
have been adjusted for negative wrap around, that is to say:
v[1] == tbl[first + 0]
v[2] == tbl[first + 1]
…
v[#v] == tbl[first + #v - 1]
Where first + #v - 1
is within the bounds of [first, last]
of tbl
.
transforms.foreach(tbl: table, adapter: function, first: number or nil, last: number or nil)
Returns an adaptation of each element in tbl
from first
to last
. Any nil
result of the adapter
is ignored, and not appended to the result.
The adapter
follows the predicate
signature except for the handling of the return values
The simple case is to return a single value. E.g. tx.foreach({'a', 'b', 'c'}, string.upper)
would return {'A', 'B', 'C'}
.
The adapter can return nil
to skip a value. E.g. tx.foreach({'1', 'foobar', '2'}, function(n) return tonumber(n) end)
would return {1, 2}
.
But the adapter
can return a second value that is used in place of the next sequence number. E.g. tx.foreach({'1','foobar','3'},function(n,i) return tonumber(n), tostring(i) end)
would return {["1"]=1, ["3"]=3}