concatenate hash values when key is same in perl

2019-02-19 10:26发布

I have a hash something like :

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

how can we concatenate the values, whose keys are same. So the output will be:

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

I tried by sorting the hash by keys then checking for each key, if they are same then concatenate the value, but i am not getting that how to compare two keys in same loop.

Thanks in advance.

标签: perl hash
4条回答
Melony?
2楼-- · 2019-02-19 10:49

If it's a list with key value pairs you are talking about then you could do something like:

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;
}
查看更多
beautiful°
3楼-- · 2019-02-19 10:56

Since it is unclear what you are really trying to do, I am guessing that you have a file that you need to change. In which case, a one-liner might be in order.

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

Output:

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

Note that the keys in the output will not be in the same order as the input. You can sort the keys if you like, but I opted not to.

Explanation:

  • -l will remove line endings while reading, and put them back while printing
  • -n will place a while(<>) loop around the program, reading the file (or STDIN) line by line.
  • // is the defined-or operator. It will return the RHS if the LHS is undefined.
  • }{ is the eskimo kiss operator which only works with the -n option. What it does is basically the same as an END block, it performs the following code at the end of the input.
查看更多
来,给爷笑一个
4楼-- · 2019-02-19 11:00

The exact way this works depends on the real source of your data, but this program shows a way to read the information from the DATA filehandle to build and dump a hash.

The values of the hash are anonymous arrays that contain all the values corresponding to the same key.

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

output

abc => 1,4
hello => 32,23,12
xyz => 18
查看更多
该账号已被封号
5楼-- · 2019-02-19 11:00
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";
}
查看更多
登录 后发表回答