tcheungcm has asked for the wisdom of the Perl Monks concerning the following question:

If I have a hash like:
'abc,def' => { ,,,item4 , item1,,, , ,item2,, }
'klm,mno' => { ,item2,, , ,,item3, , }

I want to the merge the multiple rows with the same key as follow: how should I do it ?

'abc,def' => {item1,item2,,item4 ,} 'klm,mon' => {,item2,item3, ,}
how to do it using hash? thanks

Replies are listed 'Best First'.
Re: merge with multiple row with same key
by LanX (Saint) on Nov 27, 2014 at 02:36 UTC
    please post real data using Data::Dumper

    this pseudo code doesn't make much sense and I can't even spot any difference between before and after.

    Hint: curlies denote literal anonymous hashes

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

      Here is output using Dumper
      'abc,def' => { ',,,item4' => 1, 'item1,,,' => 1, ',item2,,' => 1 }, 'kln,mno' => { ',,,item4' => 1 'item1,,,' => 1 },

      And the result should look like

      'abc,def' => { 'item1,item2,,item4 }, 'kln.mno' => { 'item1,,,item4 },

        That cannot be the output from Data::Dumper, because it lacks commas between some of the elements. When you post imprecise samples and claim that they're the output of something that generates precise, and syntactically correct data structures, we're unable to trust your problem description, much less know how to fill in the missing parts.

        Your expected result is also impossible, unless we should be interpreting it as simple text. From a Perl data structure point of view, 'abc,def' => { 'item1,item2,,item4 }, is nonsensical; the curly braces mean "anonymous hash", and the leading single quote isn't balanced by any closing single quote. Given the ambiguity introduced by leaving quotes unbalanced, we also can't determine which of the commas should be interpreted as literal text, or as operators.

        Also, since hash elements have no predictable or useful order, it would be helpful to specify how the "item1" and so on elements should be ordered (assuming you really intend for them to be array elements).

        With those flaws in the question making it impossible to precisely know what is being asked, it is also impossible to give an answer that is guaranteed to precisely match your needs. But this is an attempt at getting close:

        use Data::Dumper; my %orig = ( 'abc,def' => { ',,,item4' => 1, 'item1,,,' => 1, ',item2,,' => 1, }, 'kln,mno' => { ',,,item4' => 1, 'item1,,,' => 1, }, ); my %new; foreach my $top ( keys %orig ) { push @{$new{$top}}, $_ for keys %{$orig{$top}}; } print Dumper \%new;

        The output that produces is this:

        $VAR1 = { 'abc,def' => [ 'item1,,,', ',item2,,', ',,,item4' ], 'kln,mno' => [ 'item1,,,', ',,,item4' ] };

        Dave

        Please have a look at perldsc and stop waisting our time with fake code.

        Cheers Rolf

        (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: merge with multiple row with same key
by Cristoforo (Curate) on Nov 27, 2014 at 03:59 UTC
    Probably a better thought out solution could be made, but I think this may be what you're after.
    #!/usr/bin/perl use strict; use warnings; my %hash = ( 'abc,def' => { ',,,item4' => 1, 'item1,,,' => 1, ',item2,,' => 1 }, 'kln,mno' => { ',,,item4' => 1, 'item1,,,' => 1 }, ); my %new_hash; for my $key (keys %hash) { my @array; for (keys %{ $hash{$key}}) { my ($lead_comma,$item) = /^(,*)([^,]+)/; $array[ length $lead_comma ] = $item; } $new_hash{$key} = \@array; } use Data::Dumper; print Dumper \%new_hash; __END__ output from Data::Dumper $VAR1 = { 'abc,def' => [ 'item1', 'item2', undef, 'item4' ], 'kln,mno' => [ 'item1', undef, undef, 'item4' ] };