2

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.

rahul
  • 47
  • 2
  • 4
  • 3
    This looks like a key->value pairs, not a hash, since hash always have exactly one value associated with one key. – Oleg V. Volkov Jun 05 '12 at 15:15
  • How can you have a hash with same keys? Do you mean you have an array with `key => value` pairs? – Qtax Jun 05 '12 at 15:16
  • 4
    It is impossible for a Perl hash to have two elements with the same key. Please describe your underlying problem. – Borodin Jun 05 '12 at 15:17
  • Yes i am wrong in putting my question, this isn't a hash but a key->value pair. i am sorry for that, – rahul Jun 05 '12 at 15:21

4 Answers4

7

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
Borodin
  • 126,100
  • 9
  • 70
  • 144
3

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;
}
Qtax
  • 33,241
  • 9
  • 83
  • 121
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";
}
Oleg V. Volkov
  • 21,719
  • 4
  • 44
  • 68
0

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.
Community
  • 1
  • 1
TLP
  • 66,756
  • 10
  • 92
  • 149
  • hi TLP, I tried running this code but this gives an error like : String found where operator expected at near `print "$_=>$Rhash{$_}" for keys %Rhash'` (Might be a runaway multi-line '' string starting on line 90) (Missing semicolon on previous line?) Scalar found where operator expected near `print "$_=>$Rhash{$_}" for keys %Rhash'`. I tried to correct it but can't, as i am not much familiar with Perl one-liner. If you think i am making some mistake or you are aware of this error so please tell me. Thanks in advance – rahul Jun 06 '12 at 06:06
  • @rahul What is this I hear about line 90? Did you paste this into some other program file or something? – TLP Jun 06 '12 at 16:04