2

我有一个类似的哈希:

abc=>1
hello=>32
abc=>4
hello=>23
hello=>12
xyz=>18

我们如何连接键相同的值。所以输出将是:

abc=>"1,4"
hello=>"23,12,32"
xyz=>"18".

我尝试按键对哈希进行排序,然后检查每个键,如果它们相同,则连接值,但我不知道如何在同一个循环中比较两个键。

提前致谢。

4

4 回答 4

7

确切的工作方式取决于数据的真实来源,但该程序显示了一种从DATA文件句柄中读取信息以构建和转储散列的方法。

散列值是匿名数组,包含对应于同一键的所有值。

use strict;
use warnings;

my %data;

while (<DATA>) {
  my ($k, $v) = /\w+/g;
  push @{ $data{$k} }, $v;
}

for my $k (sort keys %data) {
  printf "%s => %s\n", $k, join ',', @{ $data{$k} };
}

__DATA__
abc=>1
hello=>32
abc=>4
hello=>23
hello=>12
xyz=>18

输出

abc => 1,4
hello => 32,23,12
xyz => 18
于 2012-06-05T15:22:40.357 回答
3

如果它是您正在谈论的带有键值对的列表,那么您可以执行以下操作:

my @kv = (
    abc=>1,
    hello=>32,
    abc=>4,
    hello=>23,
    hello=>12,
    xyz=>18,
);

my %hash;

while(@kv){
    my $k = shift @kv;
    my $v = shift @kv;

    $hash{$k} = defined $hash{$k} ? "$hash{$k},$v" : $v;
}
于 2012-06-05T15:21:46.373 回答
1
my @pairs = (
    abc=>1,
    hello=>32,
    abc=>4,
    hello=>23,
    hello=>12,
    xyz=>18,
);

my %hash;

# collect
for(my $idx = 0; $idx < scalar @pairs; $idx += 2){
    my $key = $pairs[$idx];
    my $val = $pairs[$idx+1];
    push @{ $hash{$key} }, $val;
}

# print combined
while( my ($key, $val) = each %hash ){
    print "$key = ", join(',', @$val), "\n";
}
于 2012-06-05T15:25:43.107 回答
0

由于不清楚您真正想要做什么,我猜您有一个需要更改的文件。在这种情况下,可能需要单线。

perl -lwne '
    ($k,$v) = split /=>/; 
    $data{$k} = join ",", $data{$k} // (), $v }{ 
    print "$_=>$data{$_}" for keys %data' input.txt > output.txt

输出:

hello=>32,23,12
abc=>1,4
xyz=>18

请注意,输出中的键与输入的顺序不同。您可以根据需要对键进行排序,但我选择不这样做。

解释:

  • -l将在阅读时删除行尾,并在打印时将它们放回去
  • -n将在程序周围放置一个while(<>)循环,逐行读取文件(或 STDIN)。
  • //defined-or运算符。如果 LHS 未定义,它将返回 RHS。
  • }{是仅适用于该选项的爱斯基摩吻运算符。-n它的作用与 END 块基本相同,它在输入的末尾执行以下代码。
于 2012-06-05T18:23:29.173 回答