【问题标题】:Simplest way to do "natural" sort for numbers in strings?对字符串中的数字进行“自然”排序的最简单方法?
【发布时间】:2012-06-11 08:30:47
【问题描述】:

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

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

【问题讨论】:

  • sort -n?由于您没有指定语言/环境,因此这是一个很好的答案......
  • 这篇关于自然排序的Coding Horror blog 帖子包含几个不同实现的链接。
  • “最好的”可能意味着几件事:更简单?最有效?更自然的结果?等等。

标签: algorithm natural-sort


【解决方案1】:

项目也可以是

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

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

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

  2. 现在像字符串一样对修改后的列表进行排序。

【讨论】:

  • 是的,这样所有的数字都是相同的桶长。
【解决方案2】:

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

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

  • 删除所有前导零。
  • 将数字子串长度编码为数字“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 使用这种方法。

【讨论】:

    【解决方案3】:

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

    如何将全数字标记与非数字标记进行比较取决于您,但您很可能希望foo123.txt 出现在foo.txt 之后但在fooA.txt 之前。这意味着当您将标记 foo 与标记 foo<something> 进行比较时,您不会仅基于这两个标记立即产生答案 - 您需要将 <something>foo 之后的标记进行比较。

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

    【讨论】:

      猜你喜欢
      • 2015-04-22
      • 2014-01-03
      • 2013-03-06
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 2017-02-14
      • 2011-12-09
      • 1970-01-01
      相关资源
      最近更新 更多