Lua: 自定义迭代器按颜色排序?
2016-1-25 8:27:15
收藏:0
阅读:109
评论:3
我想创建一个自定义迭代器,按颜色和数字值对这个表进行排序:
t1 = {{"green", 1},{"red", 3},{"green", 2},{"yellow", 5},{"red", 4}}
for i, v in ipairs(t1) do
Note(i," ",v[1]," ",v[2])
end
现在这会输出:
1 green 1
2 red 3
3 green 2
4 yellow 5
5 red 4
我的期望输出是:
4 yellow 5
3 green 2
1 green 1
5 red 4
2 red 3
我能用一个自定义迭代器实现这个吗?
编辑:我想要的是这样的东西,但我似乎无法解决:
function sort_colours(t) -- sort table
local T = { }
for i, v in ipairs(t) do
T[#T + 1] = { i = i, v = v }
end
local order = {yellow = 1, green = 2, red = 3} -- desired order for colors
table.sort(T, function(a, b)
-- since you seem to want large-to-small when colors are the same,
-- use b[2] < a[2] comparison
if a[1] == b[1] then return b[2] < a[2] end
return order[a[1]] < order[b[1]]
end)
for i = 1, #T do
T[i] = T[i].i
end
local i = 0
return function() -- iterator function
i = i + 1
if T[i] then
return T[i], t[T[i]]
end
end
end
local t1 = {{"green", 1},{"red", 3},{"green", 2},{"yellow", 5},{"red", 4}}
for k, v in sort_colours(t1) do print(k, v[1], v[2]) end
点赞
用户3677376
你的尝试非常接近了。你只需要记住 table.sort 的比较函数中的 a 和 b 参数是 T 数组的元素,它们有 i 和 v 字段(v 字段包含你实际想要比较的值):
function sort_colours(t)
local T = { }
for i, v in ipairs(t) do
T[#T+1] = { i = i, v = v } -- 这里也可以直接用 T[i]!
end
local order = {yellow = 1, green = 2, red = 3}
table.sort(T, function(a, b)
if a.v[1] == b.v[1] then return b.v[2] < a.v[2] end
return order[a.v[1]] < order[b.v[1]]
end)
local i = 0
return function()
i = i + 1
if T[i] then
return T[i].i, T[i].v
end
end
end
local t1 = {{"green", 1},{"red", 3},{"green", 2},{"yellow", 5},{"red", 4}}
for k, v in sort_colours(t1) do print(k, v[1], v[2]) end
你代码中的第二个 for 循环(for i = 1, #T do T[i] = T[i].i end)是不必要的,因为你基本上扔掉了你刚刚排序的大部分数据。但是我认为你想做的是这种问题的常用方法:创建(和排序)原始数组的索引数组,而不是复制数据本身。以下是一个示例(这次做得更有趣一些,作为一个更一般/可重用的函数):
-- 默认比较函数
local function lessthan(a, b)
return a < b
end
function sorted_ipairs(t, f)
f = f or lessthan
local indices = {}
for i in ipairs(t) do
indices[i] = i
end
table.sort(indices, function(a, b)
return f(t[a], t[b])
end )
local i = 1
return function()
local index = indices[i]
if index then
i = i + 1
return index, t[index]
end
end
end
local order = {yellow = 1, green = 2, red = 3}
local function colour_compare(a, b)
if a[1] == b[1] then return b[2] < a[2] end
return order[a[1]] < order[b[1]]
end
for k, v in sorted_ipairs(t1, colour_compare) do print(k, v[1], v[2]) end
只要在迭代期间,原始数组不发生更改(无论是因为添加/删除元素还是因为涉及到不良行为的 __index 元方法),两种方法都可以正常工作。如果原始数组确实发生了更改,第一种方法更可预测,因为它是基于数据快照的。
对于示例数据,两种方法的输出是相同的:
4 yellow 5
3 green 2
1 green 1
5 red 4
2 red 3
2016-01-25 10:33:38
用户3979429
在不知道您的代码原因或如何实现它的情况下,我已经创建了一个迭代器,应该会大部分时间都有效。除非您正在像评论中指出的那样非常奇怪地使用克隆。
我的方法是围绕创建表的克隆并对其进行排序,然后返回一个迭代器,以便您可以在通用循环中调用它:
t1 = {{"green", 1},{"red", 3},{"green", 2},{"yellow", 5},{"red", 4}}
function ByColor(t,order)
local order = order or {yellow=1,green=2,red=3}
local nt = {table.unpack(t)}
table.sort(nt, function(a,b)
return order[a[1]] < order[b[1]] or order[a[1]] == order[b[1]] and a[2] > b[2]
end)
local helper = 1
return function(ti,v)
local nxt = nt[helper]
helper = helper + 1
for i,v in ipairs(t) do
if v == nxt then
return i,nxt
end
end
return nil
end
end
for i,v in ByColor(t1) do
print(i,v[1],v[2])
end
它返回您表格中的实际索引,并提供一个可选参数用于排序,假设您想从黄色/绿色/红色切换。
2016-01-25 12:05:33
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
你可以在使用标准的
ipairs迭代前,保持一个按需排序的表:local t1 = {{"green", 1},{"red", 3},{"green", 2},{"yellow", 5},{"red", 4}} local order = {yellow = 1, green = 2, red = 3} -- 颜色的期望顺序 table.sort(t1, function(a, b) -- 由于您似乎希望颜色相同时按从大到小排序, -- 应使用 b[2] < a[2] 比较 if a[1] == b[1] then return b[2] < a[2] end return order[a[1]] < order[b[1]] end) for k, v in ipairs(t1) do print(k, v[1], v[2]) end -- 显示结果我得到了以下结果,这可能是您想要的: