Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Arrays and hashes only with references

by grizzley (Chaplain)
on Mar 14, 2008 at 13:50 UTC ( [id://674203]=perltutorial: print w/replies, xml ) Need Help??

I am teaching right now a friend, who wants a new job, and just yesterday thought about how to explain array of arrays or hash of hashes etc. Here is how I tried:

For a little bit forget about array (@) and hash (%) notation. Stick only to variable ($) or in other words, reference symbol and see how easy (I hope) it is.

Always when you want hash, use curly brackets {}, always if array - square brackets []. And on one nesting level treat everything as list of scalars, nothing more, nothing less.

$arrayref = [1, 3, 5, 7]; $hashref = {key1=>val1, key2=>val2, key3=>val3};

When you need some value from hash or array, do following:

# want array element - use square brackets $value = $$arrayref[2]; # want hash element - use curly brackets $othervalue = $$hashref{key2};

Lets build more complicated structure. The first rule: don't use any reference more than once while building another structure. Second rule: treat reference as normal scalar value.

# array of arrays # array - square brackets. Created three times, remember, every refere +nce can be used only once to build another structure. $arrayref1 = [1, 3, 5, 7]; $arrayref2 = [1, 3, 5, 7]; $arrayref3 = [1, 3, 5, 7]; # array of arrays - again: array = square brackets, and it is still on +ly list of scalars, nothing more $array_of_arrays = [$arrayref1, $arrayref2, $arrayref3]; # see how it looks (notice, that Dumper operates only on references. W +hat kind of brackets do you see in the dump?): use Data::Dumper; print Dumper $array_of_arrays; # now: get one element. We have three elements in hmm, lets say, 'oute +r' level, so the last one will be(array-square brackets): $$array_of_arrays[2]..... # and there are 4 values in 'inner' level, so lets take last one: $value = $$array_of_arrays[2][3];

Easy, isn't it? Now with hashes, similarly, only other brackets:

# hash of hashes # hash - curly brackets $hashref1 = {key1 => value1, key2 => value2, key3 => value3, key4 => v +alue4}; $hashref2 = {key1 => value1, key2 => value2, key3 => value3, key4 => v +alue4}; $hashref3 = {key1 => value1, key2 => value2, key3 => value3, key4 => v +alue4}; # hash of hashes, which brackets? :) $hash_of_hashes = {key11 => $hashref1, key22 => $hashref2, key33 => $h +ashref3}; # see how it looks: use Data::Dumper; print Dumper $hash_of_hashes; # get an element. Nothing surprising, starting from 'outer' level: $$hash_of_hashes{key22}......... # and end with 'inner' key $$hash_of_hashes{key22}{key4};

That's it. Easy? I think so. Lets mix the structures. The rules stay the same: use every reference only once, treat reference as a scalar, curly brackets = hash, square brackets = array.

$monk1 = 'Jack'; $monk2 = 'John'; $monk3 = 'Mark'; $monk4 = 'Rudolf'; #order of monks important - using array - square brackets $bank_left1 = [$monk1, '', $monk2]; $bank_left2 = []; $bank_left3 = []; $bank_left4 = []; # order of banks important - use array $left_nave = [$bank_left1, $bank_left2, $bank_left3, $bank_left4]; $bank_right1 = []; $bank_right2 = [$monk3]; $bank_right3 = []; $bank_right4 = []; $right_nave = [$bank_right1, $bank_right2, $bank_right3, $bank_right4] +; # existence of elements is important, order not - lets do hash $church = {'left nave'=>$left_nave, 'right nave'=>$right_nave, 'altar' +=>1, 'tabernacle'=>1}; # lets declare hash of arrays at once, order of plants not important, +but array is here more convenient. # See, instead of (key, value) pairs I use (key, reference-to-array). $garden = {'plants'=>['potato', 'carrot', 'apple tree'], 'monks'=>[$mo +nk4], 'rain'=>1}; # and finally whole monastery, not rich, but its our home :) $monastery = {'church'=>$church, 'garden'=>$garden}; # see how it looks and where monks reside: use Data::Dumper; print Dumper $monastery;

Now is time to go back to @ and %. Rules are simple: if you have reference $arrayref to an array and need to use it as array, just write @$arrayref. Similarly use $hashref as %hashref if some function needs hash. Two simple examples:

# using @ in join function $arrayref = $$monastery{'garden'}{'plants'}; print "Plants: ", join ", ", @{$arrayref}; # or @$arrayref # or just # print "Plants: ", join ", ", @{$$monastery{'garden'}{'plants'}}; # using % in keys function $hashref_churchelems = $$monastery{'church'}; print "\nChurch elements: ", join ", ", keys %{$hashref_churchelems}; # or just # print "\nChurch elements: ", join ", ", keys %{$$monastery{'church'} +}; print"\n"; # monk sitting in church -> in left nave -> in first bank -> as first print "Monk: ", $$monastery{'church'}{'left nave'}[0][0], "\n";

That's how structures look from ref point of view.

Replies are listed 'Best First'.
Re: Arrays and hashes only with references
by wade (Pilgrim) on Mar 14, 2008 at 17:16 UTC
    I code similarly to this but instead of:
    $value = $$arrayref[2];
    I prefer:
    $value = $arrayref->[2];
    The beauty of that notation is that it doesn't treat the outer level of a nest any differently.
Re: Arrays and hashes only with references
by Pancho (Pilgrim) on Mar 14, 2008 at 20:52 UTC

    Big ++ on this tutorial, since it is (a) brief and to the point, (b) step by step, (c) includes code to download and tinker with. Just what a noob (i.e. me) needs. Beggars can't be choosers but adding the alternate syntax (which Wade illustrated) would make it even better.

    Grizzley Keep 'em coming. Thanks

Re: Arrays and hashes only with references
by hsinclai (Deacon) on Sep 19, 2008 at 02:19 UTC
    ++ on your posting grizzley - this has gotten me over a huge hump !


Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perltutorial [id://674203]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-20 13:54 GMT
Find Nodes?
    Voting Booth?

    No recent polls found