Lua 按字母顺序 table 排序,数字除外
Lua sort table alphabetically, except numbers
我想按字母顺序对 table 进行排序。除了数字。
下面的代码显示了 table 如何使用比较函数排序:
function( a,b ) return a.N < b.N end
给我:
obj = {
[1] = {
["N"] = "Green 1";
};
[2] = {
["N"] = "Green 11";
};
[3] = {
["N"] = "Green 2";
};
[4] = {
["N"] = "Red 1";
};
}
但我希望它像这样排序:
obj = {
[1] = {
["N"] = "Green 1";
};
[2] = {
["N"] = "Green 2";
};
[3] = {
["N"] = "Green 11";
};
[4] = {
["N"] = "Red 1";
};
}
可能吗?
试试这个:
local function split(a)
local x,y=a.N:match("(%S+)%s+(%S+)")
return x,tonumber(y)
end
table.sort(obj,
function (a,b)
local a1,a2=split(a)
local b1,b2=split(b)
return a1<b1 or (a1==b1 and a2<b2)
end
)
@lhf 的解决方案应该适合您,尽管您可能需要考虑是否需要处理极端情况,例如将 "Green 1" 与 "Green 02" 或 "Green 2" 与 [=14 进行比较=].我回顾了几种实现字母数字排序的方法,并在关于这个主题的 blog post. You may also check the discussion on the lua mail list 中比较了它们的结果。
本来打算 post 这个,但 lhf posted 的解决方案回答了你的问题。由于您仍然遇到问题,请尝试以下操作。
local function cmp(a, b)
a = tostring(a.N)
b = tostring(b.N)
local patt = '^(.-)%s*(%d+)$'
local _,_, col1, num1 = a:find(patt)
local _,_, col2, num2 = b:find(patt)
if (col1 and col2) and col1 == col2 then
return tonumber(num1) < tonumber(num2)
end
return a < b
end
local obj = {
{ N = '1' },
{ N = 'Green1' }, -- works with optional space
{ N = 'Green' }, -- works when doesn't fit the format
{ N = 'Sky blue99' },
{ N = 'Green 11' },
{ N = 'Green 2' },
{ N = 'Red 02' }, -- works when has leading zeros
{ N = 'Red 01' }, -- works with padding spaces
{ N = 'Sky blue 42' }, -- works with multi-word color names
{ N = 99 }, -- works with numbers
}
table.sort(obj, cmp)
for i,v in ipairs(obj) do
print(i, v.N)
end
打印:
1 1
2 99
3 Green
4 Green1
5 Green 2
6 Green 11
7 Red 01
8 Red 02
9 Sky blue 42
10 Sky blue99
我想按字母顺序对 table 进行排序。除了数字。
下面的代码显示了 table 如何使用比较函数排序:
function( a,b ) return a.N < b.N end
给我:
obj = {
[1] = {
["N"] = "Green 1";
};
[2] = {
["N"] = "Green 11";
};
[3] = {
["N"] = "Green 2";
};
[4] = {
["N"] = "Red 1";
};
}
但我希望它像这样排序:
obj = {
[1] = {
["N"] = "Green 1";
};
[2] = {
["N"] = "Green 2";
};
[3] = {
["N"] = "Green 11";
};
[4] = {
["N"] = "Red 1";
};
}
可能吗?
试试这个:
local function split(a)
local x,y=a.N:match("(%S+)%s+(%S+)")
return x,tonumber(y)
end
table.sort(obj,
function (a,b)
local a1,a2=split(a)
local b1,b2=split(b)
return a1<b1 or (a1==b1 and a2<b2)
end
)
@lhf 的解决方案应该适合您,尽管您可能需要考虑是否需要处理极端情况,例如将 "Green 1" 与 "Green 02" 或 "Green 2" 与 [=14 进行比较=].我回顾了几种实现字母数字排序的方法,并在关于这个主题的 blog post. You may also check the discussion on the lua mail list 中比较了它们的结果。
本来打算 post 这个,但 lhf posted 的解决方案回答了你的问题。由于您仍然遇到问题,请尝试以下操作。
local function cmp(a, b)
a = tostring(a.N)
b = tostring(b.N)
local patt = '^(.-)%s*(%d+)$'
local _,_, col1, num1 = a:find(patt)
local _,_, col2, num2 = b:find(patt)
if (col1 and col2) and col1 == col2 then
return tonumber(num1) < tonumber(num2)
end
return a < b
end
local obj = {
{ N = '1' },
{ N = 'Green1' }, -- works with optional space
{ N = 'Green' }, -- works when doesn't fit the format
{ N = 'Sky blue99' },
{ N = 'Green 11' },
{ N = 'Green 2' },
{ N = 'Red 02' }, -- works when has leading zeros
{ N = 'Red 01' }, -- works with padding spaces
{ N = 'Sky blue 42' }, -- works with multi-word color names
{ N = 99 }, -- works with numbers
}
table.sort(obj, cmp)
for i,v in ipairs(obj) do
print(i, v.N)
end
打印:
1 1
2 99
3 Green
4 Green1
5 Green 2
6 Green 11
7 Red 01
8 Red 02
9 Sky blue 42
10 Sky blue99