Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Introduction to anonymous arrays and hashes

by sulfericacid (Deacon)
on Nov 06, 2004 at 07:47 UTC ( #405724=perlquestion: print w/ replies, xml ) Need Help??
sulfericacid has asked for the wisdom of the Perl Monks concerning the following question:

Something I've heard and seen are people using anonymous hashes and arrays and because up to this point I never came across a reason to use them, this is all new to me.

I read a few tutorials online, LP3 doesn't seem to mention it and the Perl Cookbook has a small section on it I've read but I have a few questions.

Is an anonymous hash also known as a multi-dimensional hash where you can literally have different hashes inside of a single hash?

The problem I am trying to get through is creating a mess of hashes on the fly and add records to them without having to create 150 or so different hash names.

An example of what I am trying to do would be a set of hashes for each meta tag (see below). This would be for EACH meta tag. Now in the real world, I don't want to manually create a hash for each possible meta tag.

Meta tag name Meta tag value Meta tag character count Meta tag word count Meta tag word repeat count
Real example:
Title Welcome to my website! 22 4 1 Keywords candy, food, pop, candy cane, soda, caffeine 31 5 2
This isn't what I'm really trying to do with it but this seemed to be the best way to explain what I am trying to do. I have hundreds of separate hashes I need to create dynamically and store values into and someone mentioned anonymous hashes and arrays are the way to go.

An example from http://search.cpan.org/~nwclark/perl-5.8.5/pod/perlref.pod:

$hashref = { 'Adam' => 'Eve', 'Clyde' => 'Bonnie', };
This doesn't look like anything more than single key/value pairs and I don't see examples on how to do what this script requires.

How practical are anonymous hashes and arrays? This is the first time I've ever had to do them and it's because I need dynamic hashes created without needing to create new hashes. Is the primary use for these to create arrays or hashes dynamically?

Thanks for your help wise monks.



"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Comment on Introduction to anonymous arrays and hashes
Select or Download Code
Re: Introduction to anonymous arrays and hashes
by Aighearach on Nov 06, 2004 at 07:55 UTC
Re: Introduction to anonymous arrays and hashes
by pg (Canon) on Nov 06, 2004 at 08:24 UTC
    " $hashref = { 'Adam' => 'Eve', 'Clyde' => 'Bonnie', }; This doesn't look like anything more than single key/value pairs"

    That's right, and the example you gave here creates an anonymous hash. The hash has no name, but you are able to access it, not by its name, but be ref.

    So on the same page, this

    my $aref = [1,2,3];

    creates an anonymous array.

    When a complex structure like hash of hash of hash is a tree of anonymous hashs, an anonymous hash could just as simple as the example you gave. It is not measured by complexity ;-)

Re: Introduction to anonymous arrays and hashes
by Zaxo (Archbishop) on Nov 06, 2004 at 08:35 UTC

    Another related example: list your couples by address, giving the man and woman equal billing,

    my $hashref = { Eden => [qw/Adam Eve/], Hell => [qw/Bonnie Clyde/] };
    Each hash value is a truly anonymous array, and the hash itself is anonymous, though the reference to it is named.

    After Compline,
    Zaxo

Re: Introduction to anonymous arrays and hashes
by Prior Nacre V (Hermit) on Nov 06, 2004 at 10:19 UTC

    I'm assuming this is related to a markup language such as HTML or XML.

    I'm unsure whether you are using the data to create a document or if you are extracing the data from a document. If one of these, I would suggest you use one of the HTML:: or XML:: modules on CPAN. There may be others with which I'm unfamiliar; XML::LibXML is the only one that I have a reasonable working knowledge of.

    In terms of how you might use anonymous arrays and hashes, behind the <readmore> is a script which creates a data structure to represent the following HTML fragment (and prints the content of the <em> element).

    <html lang="en"> <head> </head> <body> <h1>Heading1</h1> <p id="para1" class="first-para">This is <em>emphasied</em>. A +nd this is not.</p> </body> </html>

    Note: This code is for illustrative purposes only - I am not suggesting you include it in an application.

    This has probably raised further questions. Ask away.

    Regards,

    PN5

Re: Introduction to anonymous arrays and hashes
by demerphq (Chancellor) on Nov 06, 2004 at 10:44 UTC

    IMO the term "an anonymous X" is a term that is a bit of a distraction as it is often used as a synonym for "a reference to an X". Most times the fact that a given ref is truely anonymous is completely irrelevent to anything. In fact the only case I can think where the term means anything useful is referring to distinct notational styles of creation/declaration of the vars involved. Furthermore the fact that a given ref may be anonymous at one time does not mean that it will always be anonymous, and likewise the fact that a given ref is named at one does not mean that later on it wont be anonymous. Consider some of the examples below:

    @list_of_refs=map { +{ $_ => 1 } } 1..10; @list_of_refs=map { my %hash=($_=>1); \%hash } 1..10; my $anon_array=[]; *now_its_not_anonymous=$anon_array; @now_its_not_anonymous=(1..10); print @{$anon_array}; our @foo=(1..10); my $ref=\@foo; { # the old @foo goes away now... local @foo=[]; print @$foo; print @$ref; }

    Conclusion: the term anonymous really is only a useful distinction when considering creation/declaration notation:

    my $ref_to_anon={ a=>1 }; my %named=(a=>1); my $ref_to_named=\%named; # realistically there is no way to tell which ref is to an anonymous a +rray

    Outside of that there is no reason to use the expression as there are functionally no differences between a "reference to an array" and a "anonymous array". The latter can only be manipulated as the former. I supect the main reason people tend to use this term is brevity: if you need to describe the args to a subroutine and you want to say "reference to an array" then "anonymous array" can be an attractive alternative. Albeit a somewhat confusing one to someone who isn't aware there that really is no way for a peice of code to know if a given reference is to an anonymous or named array. This is especially true as that status may be determined at run time via dynamic scoping.

    ---
    demerphq

Re: Introduction to anonymous arrays and hashes
by TedPride (Priest) on Nov 06, 2004 at 12:16 UTC
    A bit messy perhaps, but it illustrates how anonymous hashes could be used to store your data:
    use strict; my %meta; for (split(/\n\n/, join('', <DATA>))) { split(/\n/); $meta{$_[0]} = {'val', $_[1], 'cc', $_[2], 'wc', $_[3], 'wrc', $_[ +4]}; } print $meta{Keywords}{val}; __DATA__ Title Welcome to my website! 22 4 1 Keywords candy, food, pop, candy cane, soda, caffeine 31 5 2
Re: Introduction to anonymous arrays and hashes
by dimar (Curate) on Nov 06, 2004 at 17:58 UTC

    think in terms of things you already know

    Most of the difficulty of your situation goes away when you think in terms of all-purpose simple data containers that you already know well. If you are even bare-bones familiar with either databases, or spreadsheets, or both (as is 90% of the computer literate population?) then the following recipie should be readily understandable. Moreover, it is a "general-purpose" way of looking at your problem: you can apply this recipie to every project you work on for the rest of your life.

    the recipie
    • step1: build a 'mental inventory' of all-purpose simple data containers
    • step2: look at the 'raw data' you want to work with and decide what kind of simple data container it should go into
    • step3: model that simple data container in your chosen language (perl) and make sure you know how to View, Add, Edit and Delete stuff in your simple container. These four things are called *essential operations*
    • step4: (optional) practice these steps every time you encounter new data, until it becomes automatic.
    • step5: (optional) once you have mastered the *essential operations* figure out also how to Search, Sort, and Filter.

    (if you're in a hurry, skip down to "how does this fit in with your problem" below, and save this for later as a "cheatsheet")

    how does this fit in with your problem

    To solve your problem, look at the information you are trying to store and ask yourself, "which simple data container works best for what I am trying to do?"

    Since you are working with META tags, my guess is you could get away with either a SimpleTable or a SimpleWorkbook to handle your entire project. There are numerous ways you could arrange this, but for simplicity, here is a bare-bones example of what I mean.

    ### option1 put all your meta tags in a single SimpleTable my $oMetaTagTable1 = [ {tag_name => 'description' , tag_content=>'blah blah blah'}, {tag_name => 'keywords' , tag_content=>'word1;word2;word3'}, {tag_name => 'author' , tag_content=>'gurn blansten'}, ]; ### option2 put all your meta tags in a SimpleWorkbook ### where each "worksheet" has the name of the page ### where the metatags came from my $oWkbk = {}; $oWkbk->{index_htm} = $oMetaTagTable1; $oWkbk->{about_us} = $oMetaTagTable2; $oWkbk->{products} = $oMetaTagTable4; ### option3 thru option999 ### there are many ways you could approach this ### the main thing is, just think in terms of simple ### data containers and the problem is more workable

    HTH.

      Thanks. I think mainly visually, and have in the past found it hard to translate the visual form of structures into programmable structures even though I understand them, but this has put me on the right track. Understanding means being able to apply the model to other data manipulating tasks more easily.
Re: Introduction to anonymous arrays and hashes
by bobf (Monsignor) on Nov 06, 2004 at 21:22 UTC

    If I understand your current approach correctly, you have a bunch of meta tags and each tag has a set of data associated with it (value, char count, etc). When you said you're "creating a mess of hashes on the fly", it sounds like you're either using symbolic references (don't do that) or doing something like this:

    %title = ( value => 'Welcome to my website!', char_ct => 22, word_ct => 4, repeat_ct => 1 ); %keywords = ( value => 'candy, food, pop, candy cane, soda, caffeine', char_ct => 31, word_ct => 5, repeat_ct => 2 ); etc...
    I think what you're looking for here is a hash of hashes (which is actually a hash of hash references). You could combine the %title and %keywords hashes from above into a single hash:
    %tags = ( title => { value => 'Welcome to my website!', char_ct => 22, word_ct => 4, repeat_ct => 1 }, keywords => { value => 'candy, food, pop, candy cane, soda, +caffeine', char_ct => 31, word_ct => 5, repeat_ct => 2 } );
    Now you've got a single hash to store all your data in, and you don't need to worry about creating hundreds of individually declared hashes.

    Getting data into this HoH (and accessing it) is simple. Instead of doing:

    $title{value} = 'Welcome to my website!';
    do this:
    $tags{title}{value} = 'Welcome to my website!';
    New inner (e.g., value) and outter (e.g., title) keys can be added at will.

    Keep in mind that the value of $tags{title} is actually a reference to another hash. If you wanted to use the hashrefs instead of accessing the data directly (e.g., passing it to a subroutine), you would dereference it like this:

    ( $num_chars, $num_words ) = count_chars_words( $tags{title} ); sub count_chars_words { my ( $hashref ) = @_; my $value = ${ $hashref }{value}; # count stuff and return }
    Since all of the inner hashes were set up the same, the subroutine doesn't need to know (or care) about which hashref it gets, all it knows is that there is a key named 'value' in the hash.

    What if you want to add an array to the HOH? Let's add a new key to the inner hash, whose value is an arrayref:

    $tags{keywords}{val_list} = [ ( split( ', ', $tags{keywords}{value} ) +) ]; print ${ $tags{keywords}{val_list} }[2]; # pop

    References are very powerful and provide nearly unlimited flexibility in your data structure. They are well worth learning. The obligatory reference list: perlref, perlreftut, and perldsc.

    HTH.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (15)
As of 2014-07-25 13:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (171 votes), past polls