奇怪的Perl'字典'排序行为

时间:2012-02-02 14:08:56

标签: perl tcl sorting

我正在尝试在Perl中实现Tcl字典排序,以便订购一些文件。对于那些不了解Tcl的人,你可以按照它们的值对连续整数进行排序,详情如下:

http://www.perlmonks.org/index.pl?node_id=160157

总结一下: 给定数组:

qw(
  bigbang
  x10y
  x9y
  bigboy
  bigBoy
  x11y
)

按不区分大小写的字母排序,然后区分大小写作为打破平局,然后按数字排序,除了它接受任何后续数字并将整个事物解释为排序中的单个数字,因此上述内容如下所示:

qw(
    bigbang
    bigBoy
    bigboy
    x9y
    x10y
    x11y
)

x9y出现在x10y和x11y之上,而在标准的ASCII排序中,x10y和x11y将高于x9y,因为1出现在9之前。

我试图在该链接中实现Juerd的示例作为函数,但在我的情况下,当我有一个版本号列表时,排序完全模仿Tcl字典排序,如下所示:

qw{ 1 1.0 1.01 1.2 1.02 1.0003 1.102 1.103 1.203 102a 102b 103a 103b 123 };

但是当绝对路径用于文件时,排序会混乱。

我在下面发布了一个示例脚本。如果有人能够理解为什么功能出错了,或者你可以建议一个更现代的替代方案(因为我工作的例子是10年前发布的:P),我将不胜感激。

http://pastebin.com/WM6QhzSK

如果您想查看Tcl字典排序,请查看以下链接:

http://pastebin.com/h3qMT4C2

提前致谢!

编辑: - 感谢choroba引导我找到解决方案!工作职能如下:

sub dict_sort {
  my @unsorted = @_;
  my @sorted =
    map $_->[0],
    sort {
      my $i = 0;
      {
        my $A = $a->[1][$i];
        my $B = $b->[1][$i];
        defined($A) || defined($B)       # Stop if both undef
        and (
          defined($A) <=> defined($B)  # Defined wins over undef
          or (
            $A !~ /\d/ || $B !~ /\d/ # $A or $B is non-integer
            ?    (lc $A cmp lc $B)   # ?? Stringy lowercase
              || (   $A cmp    $B)   #    -> Tie breaker
            : $A <=> $B              # :: $A and $B are integers
              or (
                length($A) <=> length($B)  # If numeric comparison returns the same, check length to sort by leading zeroes
              )
          )
          or ++$i && redo              # tie => next part
        );
      }
    }
  map [ $_, [ split /(\d+)/ ] ], @unsorted;
  return @sorted;
}

1 个答案:

答案 0 :(得分:3)

您的代码对版本字符串的工作方式不同。只需按此顺序将<{1}}添加到列表 即可。如果你希望02在2之后来,你必须在9.02 9.2时检查案例。

更新:这意味着在$A == $B之后添加or length $A <=> length $B