最简单的方法"自然"排序字符串中的数字?

时间:2012-06-11 08:30:47

标签: algorithm natural-sort

我刚看到this,我想知道实现这样的自然分类的最佳方法是什么?

通常在1,4,11,12列表中,字符串排序(在列表项中使用)返回1,11,12,4。如何实现自然排序?

enter image description here

3 个答案:

答案 0 :(得分:2)

项目也可以

[ 'screen 4 episode 13', 'screen 11 episode 1', .... ]

对于上述列表和问题中提供的样本列表,可以使用以下方法:

  1. 将元素中的数字转换为基于桶的系统,即计算任何字符串中数字的最大值。例如,在上面的列表中,值为2.现在转换元素中的数字,使其长度与最大长度相同。 因此,“屏幕4集13”将被转换为“屏幕04集13”,“屏幕11集1”将被转换为“屏幕11集01”。

  2. 现在将修改后的列表排序为字符串。

答案 1 :(得分:1)

您可以将每个字符串拆分为一系列标记。令牌由所有非数字或所有数字组成。然后对标记序列进行比较,而不是对字符串中的字符序列进行比较。非数字标记比较字符串,全数字标记使用它们的整数值相互比较。

取决于全数字令牌与非数字令牌的比较,但您很可能希望foo123.txtfoo.txt之后但在fooA.txt之前显示。这意味着当您将令牌foo与令牌foo<something>进行比较时,您不会立即仅根据这两个令牌生成答案 - 您需要将<something>与令牌进行比较关注foo

然后可以优化该基本方法,以确保您不会进行任何比严格必要的字符串拆分。

答案 2 :(得分:1)

一个有效的解决方案是为每个要排序的字符串生成一个可以按字典顺序进行比较的键,然后使用这些键对原始字符串进行排序。

要生成这些键,请从原始字符串的副本开始,然后转换表示数字的子字符串,如下所示:

  • 删除所有前导零。
  • 预先将数字子串长度编码为数字'9'重复int(len / 9)次,然后是表示len%9的数字。

例如:

1          -> 11
10         -> 210
9          -> 19
12345678   -> 812345678
987654321  -> 90987654321    // len = 9, int(len / 9) = 1, len % 9 = 0
9876543210 -> 919876543210   // len = 10, int(len / 9) = 1, len % 9 = 1

您可能还想更换按键上的标点符号,以便同等地比较“Foo 123”和“Foo-123”。

Perl模块Sort::Key::Natural使用这种方法。

相关问题