【问题标题】:Lua sort table alphabetically, except numbersLua 按字母顺序排序表,数字除外
【发布时间】:2015-01-13 08:08:27
【问题描述】:

我想按字母顺序对表格进行排序。数字除外。

下面的代码显示了如何使用比较器功能对表格进行排序:

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";
    };
}

有可能吗?

【问题讨论】:

  • 在排序之前从键中删除所有数字?只对第一个词排序?等等。如果您的表很大,或者您打算这样做,通常保留您生成的“排序键”的缓存也是一个好主意。

标签: sorting lua lua-table


【解决方案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
)

【讨论】:

  • 虽然有问题,但没有提到表中的某些字符串没有编号。所以我得到一个错误。
  • 在这一行得到错误:return a1&lt;b1 or (a1==b1 and a2&lt;b2)
  • 好的,修复它:local function split(a) if string.match(a.N, '%d+') then local x,y=a.N:match("(%D+)(%d+)") return x,tonumber(y) else local x,y = a.N,0 return x,y end end
【解决方案2】:

原本打算发布此内容,但 lhf 发布的解决方案回答了您的问题。由于您仍然遇到问题,请尝试以下操作。

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

【讨论】:

  • 谢谢,这样效果更好。将模式更改为:'^(%D+)(%d+)$' 以允许 { N = 'Green1' }, 似乎有效,但可能忽略了一些东西。
  • @Dreanh 该模式看起来不错,只要颜色名称中没有任何数字就应该可以工作,(.+) 适用于任何字符。
  • 好的,谢谢。如果我使用'^(.+)(%d+)$''^(%g)(%d+)$' 它不起作用。
  • 啊,成功了!不过发现了另一个问题,如果 N = 1 可以解决它,但如果它也可以解决就很好了。
  • @Dreanh 好的,再次更新以处理数字。这超出了您原始问题的范围,您可能需要对其进行更新,以便指定处理空格(或不处理)和数字的需要。
【解决方案3】:

@lhf 的解决方案应该适合您,但您可能需要考虑是否需要处理极端情况,例如将“Green 1”与“Green 02”或“Green 2”与“Green 02”进行比较。我回顾了几种实现字母排序的方法,并在blog post 中比较了它们的结果。您也可以查看discussion on the lua mail list 就这个主题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    • 2018-09-15
    • 2021-08-10
    • 2017-02-21
    • 1970-01-01
    相关资源
    最近更新 更多