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

Hello All,
I am looking for any assistance possible. In a nutshell, I am looking to assign an array as a "value" in a hash, then be able to extract the array, make modifications to it, then reassign the array back to the "value" of the hash. I hope this can be done or if there is a much better way, I am definatly listening. I have included the code below and have documented exactally what I am trying to accomplish on each line.

Once again, Thank you in advanve for assistance
Gary
@fruit=(Apple, pear, Bananna, Peach); # Populate Fruit Array $new_fruit="Grapes"; # Next Fruit to be added $fruit{0}=248; # Just a random number $fruit{0}{'fruit'}=@fruit; # Want to assign array to this l +ocation in hash @HoldArray=$fruit{0}{'fruit'}; # Want to assign array at ha +sh location $fruit{0}{'fruit'} to HoldArray array push (@HoldArray,$new_fruit); # Push new_fruit to array $fruit{0}{'fruit'}=@HoldArray; # Want to assign updated fru +it array to this hash location #Print out Total fruit and list fruit print "There are $fruit{0} pieces of fruit. The following is a list of + the fruit \n"; foreach ($fruit{0}{'fruit'}) { print "$_ \n"; } exit; ==== End Script ========= ==== Begin Output ======= There are 248 pieces of fruit. The following is a list of the fruit 2 ==== End Output ======== ==== Expected Output ==== There are 248 pieces of fruit. The following is a list of the fruit Apple pear Bananna Peach Grapes ==== End Expected Output ====

Replies are listed 'Best First'.
Re: Array in a Hash
by ikegami (Patriarch) on Sep 04, 2009 at 02:16 UTC

    First of all, use

    use strict; use warnings;

    Hashes can't contain arrays, just scalars. References are scalars, though, so the trick is to place references to arrays in the hash.

    $fruit{0}{'fruit'} = \@fruit; # my @HoldArray = @{ $fruit{0}{'fruit'} }; # Wasteful copying my $HoldArray = $fruit{0}{'fruit'}; push @$HoldArray, $new_fruit;

    etc

Re: Array in a Hash
by bobf (Monsignor) on Sep 04, 2009 at 02:16 UTC

    I suspect you may be trying to make things more difficult than they need to be. References can be tricky, but once you get the hang of them they make so many other things MUCH easier.

    I tried to follow the logic of your example, but I'm afraid I didn't understand the rationale for doing things they way you did. For example, you are manipulating an array inside a hash of hashes (HoH), but you never make use of either level of hash. I assume the example may be a simplified version of the real problem, so I retained that structure in my example below. If there isn't any reason to keep the HoH structure, then simply using the array would be easier.

    I rewrote your example (below). You'll notice that I added a few things. First and foremost, strict and warnings are your friends. Use them, especially when you're trying to learn new syntax. There are many problems with your example code that would have been brought to your attention had you used them. Second, a module like Data::Dumper comes in handy when trying to understand complex data structures.

    use strict; use warnings; use Data::Dumper; my @fruit = qw( Apple pear Bananna Peach ); my $new_fruit = "Grapes"; my %fruits; $fruits{0}{fruit} = \@fruit; print "Original fruits:\n", Dumper( \%fruits ); push( @{ $fruits{0}{fruit} }, $new_fruit ); print "New fruits:\n", Dumper( \%fruits ); print "There are ", scalar @{ $fruits{0}{fruit} }, " pieces of fruit:\ +n"; foreach my $f ( @{ $fruits{0}{fruit} } ) { print "$f\n"; }

    I left the code uncommented intentionally. Try to follow what is going on, but if you need help feel free to ask.

    There are lots of good resources to learn about references and visualizing data structures. If I know planetscape, she will post an extensive list. :-)

    HTH

    Update: In case planetscape is off hunting knights, start with perlref, perlreftut, perldsc, perllol, PerlMonks tutorials about references, and How can I visualize my complex data structure?.

      Hello,
      Thank you for your reply. For simplicity sake, at any one given time there can be 21 fruit baskets. Each basket will contain X number of fruit consisting of "Fruit Names". So I was trying to use the hash of 0-20, for a total of 21, ( ex. $fruit{0}=248 to identify the total number of pieces of fruit in the basket, and then use ex. $fruit{0}{'fruits'}, to contain an array of the types of fruit that make up the value of $fruit{0}.

      I see you change "There are $fruit{0} ... "to There are ", scalar @{ $fruits{0}{fruit} }, ", but I actually was wanting to use $fruit{0} to list the total pieces of fruit in the basket. So in this example, Basket 1 contain 248 pieces of fruit consisting of Apples, Pears, Bananas, Peaches, and Grapes

      Thanks
      Gary
        Here is some code that is structured based on your description.

        Coding this way does require some knowledge of perl references. Hopefully, this will show you their power and relative simplicity.

        #!/usr/bin/perl use strict; use warnings; my @basket = ( #Left bracket indicates start of a list ... (Array of h +ash-refs) # Populate Zero'th basket as a hash-ref: { count=> 254, # Expecting this many fruit here fruit=> [ qw( Apple pear Banana Peach ) ], type => "All Season" }, # End of Zero'th basket {} # First (Empty) basket is created (This is not necessary) ); # End of all baskets # Adding "Grapes" to zero'th basket ... my $fruit_ref = $basket[0]{fruit} ; push @$fruit_ref, "Grapes"; $basket[0]{count}++; # Increment how many fruit # Populate First basket with tropical fruit: $basket[1]{fruit} = [ qw|papaya guava mango| ]; $basket[1]{count} = scalar ( @{ $basket[1]{fruit} }); # Auto count $basket[1]{type} = "Tropical"; # Print fruit info.. print "Basket# Type \t\tCount \tContents -------\n"; my $basket_nbr = 0; for my $b (@basket){ $basket_nbr++; #For printing, basket numbers start with 1 print "$basket_nbr \t$b->{type} \t$b->{count} \t@{$b->{fruit} }\n +"; }
        Output:
        Basket# Type Count Contents ------- 1 All Season 255 Apple pear Banana Peach Grapes 2 Tropical 3 papaya guava mango

             Potentia vobiscum ! (Si hoc legere scis nimium eruditionis habes)

Re: Array in a Hash
by toolic (Bishop) on Sep 04, 2009 at 02:23 UTC
    I would organize the data slightly differently. See also use strict and warnings and perldsc:
    use warnings; use strict; use Data::Dumper; # Populate Array my @fruits = qw( Apple pear Bananna Peach ); # Populate Hash, using a reference to the array my %fruit = ( total => 248, fruit => \@fruits ); # Next Fruit to be added my $new_fruit = "Grapes"; push @{ $fruit{fruit} }, $new_fruit; #print Dumper(\%fruit); # Print out Total fruit and list fruit print "There are $fruit{total} pieces of fruit. "; print "The following is a list of the fruit \n"; for ( @{ $fruit{fruit} } ) { print "$_ \n"; } __END__ Actual output ============= There are 248 pieces of fruit. The following is a list of the fruit Apple pear Bananna Peach Grapes
Re: Array in a Hash
by Anonymous Monk on Sep 04, 2009 at 02:17 UTC
    #!/usr/bin/perl -- use strict; use warnings; my $hash = { one => [ 1], two => [ 2], }; $hash->{one}[2] = "three"; use Data::Dumper; print Dumper($hash); __END__ $VAR1 = { 'one' => [ 1, undef, 'three' ], 'two' => [ 2 ] };
    References quick reference