我有一个类似的哈希:
abc=>1
hello=>32
abc=>4
hello=>23
hello=>12
xyz=>18
我们如何连接键相同的值。所以输出将是:
abc=>"1,4"
hello=>"23,12,32"
xyz=>"18".
我尝试按键对哈希进行排序,然后检查每个键,如果它们相同,则连接值,但我不知道如何在同一个循环中比较两个键。
提前致谢。
确切的工作方式取决于数据的真实来源,但该程序显示了一种从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
如果它是您正在谈论的带有键值对的列表,那么您可以执行以下操作:
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;
}
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";
}
由于不清楚您真正想要做什么,我猜您有一个需要更改的文件。在这种情况下,可能需要单线。
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 块基本相同,它在输入的末尾执行以下代码。