我该如何维护我加入一个Perl哈希键的顺序?(How can I maintain the orde

2019-07-22 21:11发布

我怎样才能保持实际列表在下面的程序使用哈希计算其发生后的顺序? 例如, <DATA>

a
b
e
a
c 
d 
a
c
d
b
etc.

使用散列,我计数每个元素的发生。

我想要的是:

a  3
b  2
e  1
c  2
d  2

但下面的程序显示了我其他的。

my (%count, $line, @array_1, @array_2);
while ($line = <DATA>) {
    $count{$line}++ if ( $line =~ /\S/ );
}
@array_1 = keys(%count);
@array_2 = values(%count);
for(my $i=0; $i<$#array_1; $i++)
{
   print "$array_1[$i]\t $array_2[$i]";
}

Answer 1:

哈希值是不下令,但像往常一样,CPAN提供了一个解决方案: 领带:: IxHash

use Tie::IxHash;
my %count;
tie %count, 'Tie::IxHash';

while ($line = <DATA>) {
$count{$line}++ if ( $line =~ /\S/ );
}

while( my( $key, $value)= each %count) {
    print "$key\t $value"; 
}


Answer 2:

在哈希表的数据存储在密钥哈希码,这对于大多数目的是像随机顺序的顺序。 你也想保存每个按键的第一个出现的顺序。 下面就来解决这个问题的一种方法:

my (%count, $line, @display_order);
while ($line = <DATA>) {
    chomp $line;           # strip the \n off the end of $line
    if ($line =~ /\S/) {
        if ($count{$line}++ == 0) {
            # this is the first time we have seen the key "$line"
            push @display_order, $line;
        }
    }
}

# now @display_order holds the keys of %count, in the order of first appearance
foreach my $key (@display_order)
{
    print "$key\t $count{$key}\n";
}


Answer 3:

从perlfaq4的答案, ‘我怎样才能让我的哈希记得我把元素融入到它的顺序?’


我怎样才能让我的哈希记得我把元素融入到它的顺序?

使用来自CPAN的领带:: IxHash。

use Tie::IxHash;

tie my %myhash, 'Tie::IxHash';

for (my $i=0; $i<20; $i++) {
    $myhash{$i} = 2*$i;
    }

my @keys = keys %myhash;
# @keys = (0,1,2,3,...)


Answer 4:

只是:

my (%count, @order);
while(<DATA>) {
  chomp;
  push @order, $_ unless $count{$_}++;
}
print "$_ $count{$_}\n" for @order;
__DATA__
a
b
e
a
c
d
a
c
d
b


Answer 5:

另一种选择是大卫·金的(@xdg)简单纯粹的perl Hash::Ordered模块。 你获得订单,但其速度较慢,因为哈希值将成为幕后的对象和使用用于访问和修改散列元素的方法。

有可能是可以量化的模块到底有多少慢比普通哈希基准,但它与键/值数据结构中的小脚本和快之类的应用程序的工作,足以让我一个很酷的方式。 说明文档中提到的其他几种方法来排序的哈希为好。



Answer 6:

我不相信,这始终是一个更好的技术,但我有时用它。 而不是只具有“看到”散列类型,它可以同时存储数量和顺序注意到。

基本上,代替$count{$line}具有可见的次数, $count{$line}{count}是观察到的时间和$count{$line}{order}是在其中可看出的顺序。

my %count;
while (my $line = <DATA>) {
    chomp $line;
    if ($line =~ /\S/) {
        $count{$line} ||= { order => scalar(keys(%count)) };
        $count{$line}{count}++;
    }
}

for my $line (sort { $count{$a}{order} <=> $count{$b}{order} } keys %count ) {
    print "$line $count{$line}{count}\n";
}


Answer 7:

哈希只是阵列,直到他们在Perl正在分配的,所以如果你将它转换为一个数组,你可以在它原来的顺序遍历它:

my @array = ( z => 6,
              a => 8,
              b => 4 );

for (my $i=0; $ar[$i]; ++$i) {
    next if $i % 2;
    my $key = $ar[$i];
    my $val = $ar[$i+1];

    say "$key: $val"; # in original order
}

如果你这样做很明显,你失去的散列索引的好处。 但由于哈希只是一个数组,你可以通过指定数组的哈希创建一个:

my %hash = @array;
say $hash{z};

这也许只是对“使用数组作为索引”解决方案的变化,但我认为这是因为而不是手工输入你的索引(或以其他方式),你直接从源阵列创建它的整洁。



文章来源: How can I maintain the order of keys I add to a Perl hash?