Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Counting Hash values?

by packetstormer (Monk)
on Mar 12, 2013 at 17:15 UTC ( #1023020=perlquestion: print w/ replies, xml ) Need Help??
packetstormer has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks

I am having trouble getting my head around this one!. I have a hash like below. Each hash value is a string seperated by a "|". I need to ignore the first value (as that is the hash key) but take the next two values e.g "RED DOOR|10-14" (one for each unique string) and then push the first value into an arrayref as the value! (eyes are bleeding writing this!) so the results might be:

"RED DOOR|10-14" => [5030,1049,4990,959......] "FLOWER|13+" => [15047,17665,17668...] "FLOWER|11+" => [15037....]

Main Hash:
5030 => 5030|RED DOOR|10-14 1049 => 1049|RED DOOR|10-14 4990 => 4990|RED DOOR|10-14 959 => 959|RED DOOR|10-14 15047 => 15047|FLOWER|13+ 5565 => 5565|RED DOOR|10-14 4449 => 4449|RED DOOR|10-14 1065 => 1065|RED DOOR|10-14 2992 => 2992|RED DOOR|10-14 4956 => 4956|RED DOOR|10-14 17665 => 17665|FLOWER|13+ 6217 => 6217|RED DOOR|10-14 1224 => 1224|RED DOOR|10-14 424 => 424|RED DOOR|10-14 368 => 368|RED DOOR|10-14 451 => 451|RED DOOR|10-14 7752 => 7752|RED DOOR|10-14 4070 => 4070|RED DOOR|10-14 1312 => 1312|RED DOOR|10-14 17668 => 17668|FLOWER|13+ 4224 => 4224|RED DOOR|10-14 3588 => 3588|RED DOOR|10-14 11076 => 11076|RED DOOR|10-14 2986 => 2986|RED DOOR|10-14 2402 => 2402|RED DOOR|10-14 10834 => 10834|RED DOOR|10-14 849 => 849|RED DOOR|10-14 2954 => 2954|RED DOOR|10-14 11 => 11|RED DOOR|10-14 4093 => 4093|RED DOOR|10-14 492 => 492|RED DOOR|10-14 1861 => 1861|RED DOOR|10-14 4384 => 4384|RED DOOR|10-14 15037 => 15037|FLOWER|11+ 13044 => 13044|FLOWER|13+ 899 => 899|RED DOOR|10-14 292 => 292|RED DOOR|10-14 10421 => 10421|RED DOOR|10-14 4120 => 4120|RED DOOR|10-14 5557 => 5557|RED DOOR|10-14 3859 => 3859|RED DOOR|10-14 930 => 930|RED DOOR|10-14 649 => 649|RED DOOR|10-14 7511 => 7511|RED DOOR|10-14 648 => 648|RED DOOR|10-14 73 => 73|RED DOOR|10-14 12537 => 12537|RED DOOR|10-14 2485 => 2485|RED DOOR|10-14

I am having trouble figuring out how to push the value into what will be a dynamic array name? That is, I will never know the values as there a generated from a SQL query.

Any pointers would be great.

Comment on Counting Hash values?
Select or Download Code
Re: Counting Hash values?
by thundergnat (Deacon) on Mar 12, 2013 at 17:38 UTC

    Maybe something like:

    use warnings; use strict; use Data::Dumper; my %hash = map { chomp; split ' => ', $_ } <DATA>; my %out; for (values %hash) { my ($val, $key) = split /\|/, $_, 2; push @{$out{$key}}, $val; } print Dumper \%out; __DATA__ 5030 => 5030|RED DOOR|10-14 1049 => 1049|RED DOOR|10-14 4990 => 4990|RED DOOR|10-14 959 => 959|RED DOOR|10-14 15047 => 15047|FLOWER|13+ 5565 => 5565|RED DOOR|10-14 4449 => 4449|RED DOOR|10-14 1065 => 1065|RED DOOR|10-14 2992 => 2992|RED DOOR|10-14 4956 => 4956|RED DOOR|10-14 17665 => 17665|FLOWER|13+ 6217 => 6217|RED DOOR|10-14 1224 => 1224|RED DOOR|10-14 424 => 424|RED DOOR|10-14 368 => 368|RED DOOR|10-14 451 => 451|RED DOOR|10-14 7752 => 7752|RED DOOR|10-14 4070 => 4070|RED DOOR|10-14 1312 => 1312|RED DOOR|10-14 17668 => 17668|FLOWER|13+ 4224 => 4224|RED DOOR|10-14 3588 => 3588|RED DOOR|10-14 11076 => 11076|RED DOOR|10-14 2986 => 2986|RED DOOR|10-14 2402 => 2402|RED DOOR|10-14 10834 => 10834|RED DOOR|10-14 849 => 849|RED DOOR|10-14 2954 => 2954|RED DOOR|10-14 11 => 11|RED DOOR|10-14 4093 => 4093|RED DOOR|10-14 492 => 492|RED DOOR|10-14 1861 => 1861|RED DOOR|10-14 4384 => 4384|RED DOOR|10-14 15037 => 15037|FLOWER|11+ 13044 => 13044|FLOWER|13+ 899 => 899|RED DOOR|10-14 292 => 292|RED DOOR|10-14 10421 => 10421|RED DOOR|10-14 4120 => 4120|RED DOOR|10-14 5557 => 5557|RED DOOR|10-14 3859 => 3859|RED DOOR|10-14 930 => 930|RED DOOR|10-14 649 => 649|RED DOOR|10-14 7511 => 7511|RED DOOR|10-14 648 => 648|RED DOOR|10-14 73 => 73|RED DOOR|10-14 12537 => 12537|RED DOOR|10-14 2485 => 2485|RED DOOR|10-14
Re: Counting Hash values?
by toolic (Chancellor) on Mar 12, 2013 at 17:42 UTC
    perldsc
    use warnings; use strict; my %data = ( 5030 => '5030|RED DOOR|10-14', 1049 => '1049|RED DOOR|10-14', 4990 => '4990|RED DOOR|10-14', 959 => '959|RED DOOR|10-14', 15047 => '15047|FLOWER|13+', 5565 => '5565|RED DOOR|10-14', 4449 => '4449|RED DOOR|10-14', 1065 => '1065|RED DOOR|10-14', 2992 => '2992|RED DOOR|10-14', 4956 => '4956|RED DOOR|10-14', 17665 => '17665|FLOWER|13+', 6217 => '6217|RED DOOR|10-14', 1224 => '1224|RED DOOR|10-14', 424 => '424|RED DOOR|10-14', 368 => '368|RED DOOR|10-14', 451 => '451|RED DOOR|10-14', 7752 => '7752|RED DOOR|10-14', 4070 => '4070|RED DOOR|10-14', 1312 => '1312|RED DOOR|10-14', 17668 => '17668|FLOWER|13+', 4224 => '4224|RED DOOR|10-14', 3588 => '3588|RED DOOR|10-14', 11076 => '11076|RED DOOR|10-14', 2986 => '2986|RED DOOR|10-14', 2402 => '2402|RED DOOR|10-14', 10834 => '10834|RED DOOR|10-14', 849 => '849|RED DOOR|10-14', 2954 => '2954|RED DOOR|10-14', 11 => '11|RED DOOR|10-14', 4093 => '4093|RED DOOR|10-14', 492 => '492|RED DOOR|10-14', 1861 => '1861|RED DOOR|10-14', 4384 => '4384|RED DOOR|10-14', 15037 => '15037|FLOWER|11+', 13044 => '13044|FLOWER|13+', 899 => '899|RED DOOR|10-14', 292 => '292|RED DOOR|10-14', 10421 => '10421|RED DOOR|10-14', 4120 => '4120|RED DOOR|10-14', 5557 => '5557|RED DOOR|10-14', 3859 => '3859|RED DOOR|10-14', 930 => '930|RED DOOR|10-14', 649 => '649|RED DOOR|10-14', 7511 => '7511|RED DOOR|10-14', 648 => '648|RED DOOR|10-14', 73 => '73|RED DOOR|10-14', 12537 => '12537|RED DOOR|10-14', 2485 => '2485|RED DOOR|10-14', ); my %hoa; for my $k (keys %data) { my ($k2) = $data{$k} =~ /.*?\|(.*)/; push @{ $hoa{$k2} }, $k; } use Data::Dumper; $Data::Dumper::Sortkeys=1; print Dumper(\%hoa);

    If original hash order is important, use Tie::IxHash

      Great thanks!

      It still amazes me how quickly you guys can answers things like this, I've been trying to figure this out for a couple of hours - shows my standard I suppose!
Re: Counting Hash values?
by blue_cowdawg (Monsignor) on Mar 12, 2013 at 17:45 UTC

    check out the following:

    use strict; use Data::Dumper; my %hash=(); while(my $line=<DATA>){ chomp $line; my($key,$val)=split(/\s+=>\s+/,$line); my ($j,@k)=split(/[\|]/,$val); my $realkey=join('|',@k); if ( ! exists($hash{$realkey}) ){ $hash{$realkey}=[]; } push @{$hash{$realkey}},$key; } print Dumper(\%hash); __END__ 5030 => 5030|RED DOOR|10-14 1049 => 1049|RED DOOR|10-14 4990 => 4990|RED DOOR|10-14 959 => 959|RED DOOR|10-14 15047 => 15047|FLOWER|13+ 5565 => 5565|RED DOOR|10-14 4449 => 4449|RED DOOR|10-14 1065 => 1065|RED DOOR|10-14 2992 => 2992|RED DOOR|10-14 4956 => 4956|RED DOOR|10-14 17665 => 17665|FLOWER|13+ 6217 => 6217|RED DOOR|10-14 1224 => 1224|RED DOOR|10-14 424 => 424|RED DOOR|10-14 368 => 368|RED DOOR|10-14 451 => 451|RED DOOR|10-14 7752 => 7752|RED DOOR|10-14 4070 => 4070|RED DOOR|10-14 1312 => 1312|RED DOOR|10-14 17668 => 17668|FLOWER|13+ 4224 => 4224|RED DOOR|10-14 3588 => 3588|RED DOOR|10-14 11076 => 11076|RED DOOR|10-14 2986 => 2986|RED DOOR|10-14 2402 => 2402|RED DOOR|10-14 10834 => 10834|RED DOOR|10-14 849 => 849|RED DOOR|10-14 2954 => 2954|RED DOOR|10-14 11 => 11|RED DOOR|10-14 4093 => 4093|RED DOOR|10-14 492 => 492|RED DOOR|10-14 1861 => 1861|RED DOOR|10-14 4384 => 4384|RED DOOR|10-14 15037 => 15037|FLOWER|11+ 13044 => 13044|FLOWER|13+ 899 => 899|RED DOOR|10-14 292 => 292|RED DOOR|10-14 10421 => 10421|RED DOOR|10-14 4120 => 4120|RED DOOR|10-14 5557 => 5557|RED DOOR|10-14 3859 => 3859|RED DOOR|10-14 930 => 930|RED DOOR|10-14 649 => 649|RED DOOR|10-14 7511 => 7511|RED DOOR|10-14 648 => 648|RED DOOR|10-14 73 => 73|RED DOOR|10-14 12537 => 12537|RED DOOR|10-14 2485 => 2485|RED DOOR|10-14
    which when run gives you:
    $VAR1 = { 'FLOWER|11+' => [ '15037' ], 'RED DOOR|10-14' => [ '5030', '1049', '4990', '959', '5565', '4449', '1065', '2992', '4956', '6217', '1224', '424', '368', '451', '7752', '4070', '1312', '4224', '3588', '11076', '2986', '2402', '10834', '849', '2954', '11', '4093', '492', '1861', '4384', '899', '292', '10421', '4120', '5557', '3859', '930', '649', '7511', '648', '73', '12537', '2485' ], 'FLOWER|13+' => [ '15047', '17665', '17668', '13044' ] };

    Now... your challenge is to understand what the code is doing. :-)


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Counting Hash values?
by denishowe (Acolyte) on Mar 12, 2013 at 17:45 UTC
    Ignore the input keys, split each value on its first "|", collect all unique preceding numbers hashed by following string.
    foreach (values %in) { /(.*?)\|(.*)/; $out{$2}{$1} = 1; }
    Convert %out values from hash ref to array of keys
    foreach (values %out) { $_ = [sort keys %$_]; } # $out{"RED DOOR|10-14"}[0] = 73 etc
    I'm assuming there may be repeated values in the input but you only want each number once per key in the output.
Re: Counting Hash values?
by Kenosis (Priest) on Mar 12, 2013 at 18:19 UTC

    One more option:

    use warnings; use strict; use Data::Dumper; my %hash; my %data = ( 5030 => '5030|RED DOOR|10-14', 1049 => '1049|RED DOOR|10-14', 4990 => '4990|RED DOOR|10-14', 959 => '959|RED DOOR|10-14', 15047 => '15047|FLOWER|13+', 5565 => '5565|RED DOOR|10-14', 4449 => '4449|RED DOOR|10-14', 1065 => '1065|RED DOOR|10-14', 2992 => '2992|RED DOOR|10-14', 4956 => '4956|RED DOOR|10-14', 17665 => '17665|FLOWER|13+', 6217 => '6217|RED DOOR|10-14', 1224 => '1224|RED DOOR|10-14', 424 => '424|RED DOOR|10-14', 368 => '368|RED DOOR|10-14', 451 => '451|RED DOOR|10-14', 7752 => '7752|RED DOOR|10-14', 4070 => '4070|RED DOOR|10-14', 1312 => '1312|RED DOOR|10-14', 17668 => '17668|FLOWER|13+', 4224 => '4224|RED DOOR|10-14', 3588 => '3588|RED DOOR|10-14', 11076 => '11076|RED DOOR|10-14', 2986 => '2986|RED DOOR|10-14', 2402 => '2402|RED DOOR|10-14', 10834 => '10834|RED DOOR|10-14', 849 => '849|RED DOOR|10-14', 2954 => '2954|RED DOOR|10-14', 11 => '11|RED DOOR|10-14', 4093 => '4093|RED DOOR|10-14', 492 => '492|RED DOOR|10-14', 1861 => '1861|RED DOOR|10-14', 4384 => '4384|RED DOOR|10-14', 15037 => '15037|FLOWER|11+', 13044 => '13044|FLOWER|13+', 899 => '899|RED DOOR|10-14', 292 => '292|RED DOOR|10-14', 10421 => '10421|RED DOOR|10-14', 4120 => '4120|RED DOOR|10-14', 5557 => '5557|RED DOOR|10-14', 3859 => '3859|RED DOOR|10-14', 930 => '930|RED DOOR|10-14', 649 => '649|RED DOOR|10-14', 7511 => '7511|RED DOOR|10-14', 648 => '648|RED DOOR|10-14', 73 => '73|RED DOOR|10-14', 12537 => '12537|RED DOOR|10-14', 2485 => '2485|RED DOOR|10-14', ); /(.+?)\|(.+)/ and push @{$hash{$2}}, $1 for values %data; print Dumper \%hash;

    Partial output:

    $VAR1 = { 'FLOWER|11+' => [ '15037' ], 'RED DOOR|10-14' => [ '1049', '5030', '959', '4990', '5565', '1065', '4449', ...
Re: Counting Hash values?
by kcott (Abbot) on Mar 12, 2013 at 22:31 UTC

    G'day packetstormer,

    I'm unsure whether your input data is raw data as you've presented it:

    5030 => 5030|RED DOOR|10-14 ...

    or an actual hash (which you've called "Main Hash"); this would look different to how you've presented it:

    5030 => '5030|RED DOOR|10-14', ...

    If the former, the following code should do what you want. I have tested this but I'm not going to repost the input data and Dumper output: it's no different to what's been posted several times already.

    my %extract; while (<>) { /\s(\d+)\|(.*)\Z/ && push @{$extract{$2}}, $1; }

    [I acknowledge the similarity to the technique used by Kenosis. If your input is an actual hash; I'd recommend using that code.]

    -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1023020]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (4)
As of 2014-09-21 20:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (175 votes), past polls