-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtablex.lua
More file actions
289 lines (237 loc) · 5.94 KB
/
Copy pathtablex.lua
File metadata and controls
289 lines (237 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
local _G = _G
local print, type, next, select, tostring, getmetatable, setmetatable
= print, type, next, select, tostring, getmetatable, setmetatable
local int = math.floor
local concat = table.concat
local pack, unpack
local outdated = tonumber(_G._VERSION:sub(5)) <= 5.1
if outdated then
function pack(...)
return {..., n = select('#', ...)}
end
unpack = _G.unpack or require "tablex.unpack"
else
pack = table.pack
unpack = table.unpack
end
local Array, Table = {}, {}
-- 数组转字符串
-- 对于表的递归, 也只会取数组部分
function Array:tostring(sep, start, stop)
if type(self) ~= "table" then
return tostring(self)
end
local str_list = {}
local index = 1
local value = self[1]
while value ~= nil do
str_list[index] = value == self
and "self"
or Array.tostring(value)
index = index + 1
value = self[index]
end
sep = sep or ", "
start = start or 1
stop = stop or index - 1
return "{"..concat(str_list, sep, start, stop).."}"
end
Table._TOSTRING_DEPTH = 10 -- 默认的递归深度
-- 完整的 table 转字符串
-- 内容可能很多, 需要限制递归深度
function Table:tostring(max_depth, indent)
max_depth = max_depth or Table._TOSTRING_DEPTH
indent = indent or 0
local typ = type(self)
if typ == "string" then
return indent > 0 and ("%q"):format(self) or self
end
if typ ~= "table"
or indent >= max_depth then
return tostring(self)
end
local lines = {}
local prefix = (" "):rep(indent)
local key_str, val_str
for key, val in next, self do
key_str = (
type(key) == "string"
and "[%q]"
or "[%s]"
):format(key)
val_str = (val ~= _G) and (
val ~= self and
Table.tostring(val, max_depth, indent + 1)
or "self"
) or "_G" -- 排除_G与自引用,防止栈溢出
lines[#lines+1] = ("%s %s = %s"):format(prefix, key_str, val_str)
end
return ("{\n%s\n%s}"):format(
concat(lines, ",\n"),
prefix
)
end
Table._PRINT_DEPTH = 3
-- 打印 table (多参数, 类似 print)
function Table.print(...)
local args = pack(...)
for i = 1, args.n do
args[i] = Table.tostring(args[i], Table._PRINT_DEPTH)
end
return print(unpack(args, 1, args.n))
end
-- 多数组专用 print
function Array.print(...)
local args = pack(...)
for i = 1, args.n do
args[i] = Array.tostring(args[i])
end
return print(concat(args, '\n', 1, args.n))
end
-- 智能打印, 自动识别 tostring 模式
local function M_print(...)
local nargs = select('#', ...)
if nargs == 0 then return print("<no value>") end
if nargs >= 2 then return Table.print(...) end
if type(...) ~= "table" then
return print(tostring(...))
end
local m = (nil ~= (...)[1] or not next(...)) and Array or Table
return print(m.tostring(...))
end
local dirs_MT = {
__tostring = Array.tostring; -- 方便直接 print 查看
}
-- 列出对象的所有字段
function Table:dir()
self = nil ~= self and (
type(self) == "table"
and self
or getmetatable(self)
or error(("The object (%s) has no accessible namespace.")
:format(tostring(self)), 2)
) or _G
local dirs = {}
local index = 0
for key in next, self do
index = index + 1
dirs[index] = key
end
dirs.n = index
return setmetatable(dirs, dirs_MT)
end
-- 获取表中元素数量
function Table:size()
local size = 0
for _ in next, self do size = size + 1 end
return size
end
-- 获取最大正整数键
Array.maxn = table.maxn
if not Array.maxn then
function Array:maxn()
local max = 0
for key in next, self do
max = type(key) == "number" -- 需要是数字
and key > max -- 需要最大
and key == int(key) -- 需要是整数
and key or max
end
return max
end
end
Table.maxn = Array.maxn
-- 用另一个表的值扩展一个表 (默认覆写)
function Table:extend(other, avoid_covering)
for k, v in next, other do
if not avoid_covering or self[k] == nil then
self[k] = v
end
end
return self
end
-- 合并两个表, 得到新的表 (默认覆写)
function Table:union(other, avoid_covering)
return Table.extend(
Table.extend({}, self),
other,
avoid_covering
)
end
-- 深拷贝
function Table:clone(no_MT, copyOf)
if type(self) ~= "table" then
return self -- 非 table 类型直接返回自身
end
if copyOf and copyOf[self] then
return copyOf[self] -- 处理循环引用
end
local replica = {}
copyOf = copyOf or {} -- 记录已复制的表,避免重复
copyOf[self] = replica
for k, v in next, self do
replica[k] = Table.clone(v, no_MT, copyOf) -- 递归复制
end
-- 是否不设置元表? 默认会设置 (no_MT = nil)
if no_MT then return replica end
return setmetatable(replica, getmetatable(self))
end
-- 分离 table 的常用表部分和正整数键部分
function Table:detach()
local array = {}
local table = {}
for k, v in next, self do
if type(k) == "number"
and k > 0
and k == int(k) then
array[k] = v
else
table[k] = v
end
end
return table, array
end
-- 提取 table 的纯数组 (连续正整数键) 部分
function Array:extract()
local array = {}
local index = 1
local value = self[1]
while value ~= nil do
array[index] = value
index = index + 1
value = self[index]
end
return array
end
-- 计算数组部分的实际长度
function Array:length()
local index = 1
local value = self[1]
while value ~= nil do
index = index + 1
value = self[index]
end
return index - 1
end
local M = {
table = Table;
array = Array;
print = M_print;
dir = Table.dir; -- 拿出来方便使用
maxn = Table.maxn; -- 全版本 maxn
pack = pack; -- 全版本 pack
unpack = unpack; -- 全版本 unpack
}
-- 导出组
M.__exports = {
{
_G,
printt = M_print;
dir = Table.dir;
pack = outdated and pack or nil;
unpack = outdated and unpack or nil;
};
Table;
}
Table[1] = _G.table
return M