Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Array of arrays?

by remluvr (Sexton)
on Mar 01, 2012 at 17:17 UTC ( [id://957268]=perlquestion: print w/replies, xml ) Need Help??

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

Hi there everybody.
After two years of no coding at all, I'm back to perl, but it seems like I've lost all my (very few indeed) knowledge.
My problem now is this one. I have an input file which looks like the following:

alligator-n amphibian_reptile event sleep-v alligator-n amphibian_reptile event swim-v alligator-n amphibian_reptile event walk-v alligator-n amphibian_reptile hyper animal-n alligator-n amphibian_reptile hyper beast-n alligator-n amphibian_reptile hyper carnivore-n alligator-n amphibian_reptile mero foot-n alligator-n amphibian_reptile mero jaw-n

What I need to do is check for the value in the third column to be "hyper" and, if it is, create a hash which has the value in the first column as a key and the list of all the corresponding fourth column values as value.
Basically I'd like for it to be: alligator-n-->(animal-n, beast-n, carnivore-n)

I managed to do very little since it looks like I'm incapable of grasping the concept of list.
I did the following:

my $target; my $type; my $rel; my $relatum; my %rel=(); my %seen = (); my %relof=(); my @target; my @relatum; my$el; open INPUTTOPROCESS,$input_filetuple; while(<INPUTTOPROCESS>){ chomp; ($target,$type,$rel,$relatum) = split "[\t ]+",$_; if ($rel =~ m/hyper/) { print $target."==>".$relatum."\n"; if (!($seen{"target"}{$target}++)) { push @target,$target; } if (!$seen{"relatum"}{$relatum}++) { push @relatum,$relatum; } } print $target."==>"; #$relof{$target} = @relatum; foreach $el (@relatum){ print $el.", "; } print "\n"; }

but I know it is wrong in oh so many ways.
I'm very disappointed in myself and every suggestion would be really appreciated so I can finally grasp how this works.
Thanks.
Giulia

Replies are listed 'Best First'.
Re: Array of arrays?
by toolic (Bishop) on Mar 01, 2012 at 17:31 UTC
    This uses a hash-of arrays:
    use warnings; use strict; use Data::Dumper; $Data::Dumper::Sortkeys=1; my %animals; while (<DATA>) { my @cols = split; next unless $cols[2] eq 'hyper'; push @{ $animals{$cols[0]} }, $cols[3]; } print Dumper(\%animals); __DATA__ alligator-n amphibian_reptile event sleep-v alligator-n amphibian_reptile event swim-v alligator-n amphibian_reptile event walk-v alligator-n amphibian_reptile hyper animal-n alligator-n amphibian_reptile hyper beast-n alligator-n amphibian_reptile hyper carnivore-n alligator-n amphibian_reptile mero foot-n alligator-n amphibian_reptile mero jaw-n

    prints:

    $VAR1 = { 'alligator-n' => [ 'animal-n', 'beast-n', 'carnivore-n' ] };

    See also:

Re: Array of arrays?
by kcott (Archbishop) on Mar 01, 2012 at 17:56 UTC

    Here's a working solution that, I believe, does all the things you want.

    #!/usr/bin/env perl use strict; use warnings; my $wanted_type = q{hyper}; my %data_capture = (); while (<DATA>) { my @fields = split; if ($fields[2] eq $wanted_type) { push @{$data_capture{$fields[0]}}, $fields[3]; } } for my $key (keys %data_capture) { print $key, q{-->(}, join(q{, }, @{$data_capture{$key}}), qq{)\n}; } __DATA__ alligator-n amphibian_reptile event sleep-v alligator-n amphibian_reptile event swim-v alligator-n amphibian_reptile event walk-v alligator-n amphibian_reptile hyper animal-n alligator-n amphibian_reptile hyper beast-n alligator-n amphibian_reptile hyper carnivore-n alligator-n amphibian_reptile mero foot-n alligator-n amphibian_reptile mero jaw-n

    This code outputs:

    $ pm_array_of_arrays.pl alligator-n-->(animal-n, beast-n, carnivore-n)

    Update: I simplified the if statement because autovivification handles what I (superfluously) coded. It use to look like this:

    if ($fields[2] eq $wanted_type) { if (! exists $data_capture{$fields[0]}) { $data_capture{$fields[0]} = []; } push @{$data_capture{$fields[0]}}, $fields[3]; }

    -- Ken

Re: Array of arrays?
by Marshall (Canon) on Mar 01, 2012 at 17:34 UTC
    Try this out. The value of the hash is a reference to an array. You can push a value onto that array just like a simple @array.
    #!/usr/bin/perl -w use strict; use Data::Dumper; my %descriptions; while (<DATA>) { my ($animal,$hyper,$description) = (split)[0,2,3]; if ($hyper eq 'hyper') { push @{$descriptions{$animal}}, $description; } } print Dumper \%descriptions; =prints $VAR1 = { 'alligator-n' => [ 'animal-n', 'beast-n', 'carnivore-n' ] }; =cut __DATA__ alligator-n amphibian_reptile event sleep-v alligator-n amphibian_reptile event swim-v alligator-n amphibian_reptile event walk-v alligator-n amphibian_reptile hyper animal-n alligator-n amphibian_reptile hyper beast-n alligator-n amphibian_reptile hyper carnivore-n alligator-n amphibian_reptile mero foot-n alligator-n amphibian_reptile mero jaw-n
Re: Array of arrays?
by remluvr (Sexton) on Mar 01, 2012 at 21:08 UTC

    Thanks everybody. I really appreciate your help.
    I will now try some of your suggestion and try to improve my skills. Thanks again!

Re: Array of arrays?
by JavaFan (Canon) on Mar 01, 2012 at 17:26 UTC
    Untested:
    use autodie; open my $fh, "<", $input_filetuple; my %data; # Collects data while (<$fh>) { chomp; my ($key, undef, undef, $value) = split; push @{$data{$key}}, $value; }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-04-24 02:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found