【问题标题】:Perl hash of array - numerical sort of alphanumeric keys数组的 Perl 哈希 - 字母数字键的数字排序
【发布时间】:2011-12-26 21:48:06
【问题描述】:

我知道 Perl 中的默认排序是 ASCII 排序,而不是数字。但是如何对有数字的字符串进行数字排序呢?

例如,我有一个数组哈希,如下所示:

myhash{ANN20021015_0101_XML_71.9} = ("anta", "hunna", "huma");
myhash{ANN20021115_0049_XML_14.1} = ("lqd", "qAl", "arrajul");
myhash{ANN20021115_0049_XML_14.2} = ("anna", "alwalada");

我只需要对键进行排序...但排序是字符串中的数字。我不能进行字符串排序,因为我在 "1" 之后得到了 "10",但我也不能进行数字排序!

【问题讨论】:

标签: arrays perl sorting hash alphanumeric


【解决方案1】:

首先,您的代码不是有效的 Perl,并且可能不会按照您的想法执行。总是

  use strict;
  use warnings;

在你的程序的头部解决任何简单的错误。代码应该是这样的

  $myhash{'ANN20021015_0101_XML_71.9'} = ["anta", "hunna", "huma"];
  $myhash{'ANN20021115_0049_XML_14.1'} = ["lqd", "qAl", "arrajul"];
  $myhash{'ANN20021115_0049_XML_14.2'} = ["anna", "alwalada"];

要对除整个值之外的其他内容进行排序,您可以在排序块内转换 $a 和 $b,并以数字形式对结果进行排序 <=> 而不是字符串形式的 <=>。这段代码可以满足您的需要

  my @sorted = sort {
    my ($aa) = $a =~ /.*_(.+)/;
    my ($bb) = $b =~ /.*_(.+)/;
    $aa <=> $bb;
  } keys %myhash;

但如果您有大量数据,使用Schwartzian Transform 可能会有利可图,这将避免每次比较字符串时都提取数字部分

  my @sorted = map  { $_->[0] }
               sort { $a->[1] cmp $b->[1] }
               map  { /.*_(.+)/ and [$_, $1] }
               keys %myhash;

【讨论】:

    【解决方案2】:

    您需要进行自定义排序:将字符串切割成您知道是文字/数字的部分,并根据需要进行比较。

    从您的示例看来,您需要literal.digits,但您可以更改正则表达式以使其适合您。

    my $cut = qr/(.*?\.)(\d+)(.*)/;
    sort { 
        my @a = $a =~ $cut; my @b = $b =~ $cut; 
        $a[0] cmp $b[0] || $a[1] <=> $b[1] || $a[2] cmp $b[2] 
    } keys %myhash;
    

    另见Borodin's answer。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-16
      • 2014-04-13
      • 2016-01-26
      • 2014-08-03
      • 2016-04-27
      • 2011-02-23
      • 1970-01-01
      • 2013-05-19
      相关资源
      最近更新 更多