Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
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 (Prior) 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 surveying the Monastery: (8)
As of 2014-08-21 18:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (141 votes), past polls