Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

hash problem

by m.y (Novice)
on Jul 09, 2004 at 18:08 UTC ( [id://373210]=perlquestion: print w/replies, xml ) Need Help??

m.y has asked for the wisdom of the Perl Monks concerning the following question:

Suppose I have an array:
my @keys = qw(one two three);
How can I create a hash whose keys are the values in @keys ?
It should look like this:

$hash = { 'one' => { 'two' => { 'three' => 1 } } };

Replies are listed 'Best First'.
Re: hash problem
by tinita (Parson) on Jul 09, 2004 at 18:20 UTC
    # more or less untested my $hash = {}; pushref($hash, qw(one two three)); sub pushref { my ($hash,@array) = @_; my $ref = \$hash; for (@array) { $ref = \$$ref->{$_}; } $$ref = 1; $_[0] = $hash; } # UPDATE: simplified and tested my $hash = {}; my $ref = \$hash; for (qw(one two three)) { $ref = \$$ref->{$_}; } $$ref = 1; print Dumper $hash;
Re: hash problem
by BrowserUk (Patriarch) on Jul 09, 2004 at 19:40 UTC

    I'm sure I saw this done without the temp var $x once?

    my @a = qw[ one two three ]; my $x = 1; $hash = {}, $hash->{ $_ } = $x, $x = $hash for reverse @a; print Dumper $hash; $VAR1 = { 'one' => { 'two' => { 'three' => 1 } } };

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
      Without $x:
      my @keys = qw(one two three); my $hash = 1; $hash = { $_=> $hash } for reverse @keys;
      Of course this fails if @keys is empty

      Dave.

        That's the one :)


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re: hash problem
by sacked (Hermit) on Jul 09, 2004 at 19:57 UTC
    sub make_hash { my $keys= shift; return 1 unless $keys and @$keys; + my $key= shift @$keys; + return { $key => make_hash( $keys ) }; } + my $hash= make_hash( [qw(one two three)] ); + use Data::Dumper; print Dumper $hash; + __END__ $VAR1 = { 'one' => { 'two' => { 'three' => 1 } } };

    --sacked
Re: hash problem
by CountZero (Bishop) on Jul 09, 2004 at 18:25 UTC
    Are you really trying to make an anonymous 'Hash of a Hash of a Hash'? $hash will contain a reference to this anonymous HoHoH.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: hash problem
by nimdokk (Vicar) on Jul 09, 2004 at 18:19 UTC
    Are you looking for something like this:

    @keys=qw(one two three); %hash = { $key[0]=>'1', $key[1]=>'2', $key[2]=>'3', }
Re: hash problem
by sweetblood (Prior) on Jul 09, 2004 at 18:23 UTC
      Are you sure it works? When I inspect your @hash with print Dumper(\@hash); all I get is $VAR1 = [];

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

        You want print Dumper \%hash, not \@hash.

        @hash{@keys} is a hash slice, not an array.

        --sacked
        perhaps I'm mistaken but I don't think so, try:
        print Dumper %hash
        If I'm wrong then I've mis-understood something

        Sweetblood

Re: hash problem
by delirium (Chaplain) on Jul 09, 2004 at 19:43 UTC
    Eval to the rescue?

    @keys=qw/one two three/; $e = '%hash = (' . (shift @keys) . '=>'; $e .= '{' . $_ . '=>' for @keys; $e .= '1'; $e .= '}' for @keys; $e .= ');'; eval $e; use Data::Dumper; print Dumper \%hash;
      Darn it! I knew I should have posted my DON'T USE EVAL FOR THIS warning. As soon as this topic comes up, some fool (in this case delirium) comes along and tries to use eval.

      Get it? Never use eval for this. {sigh}

      And I wondered "Oh, maybe this time, we'll get through this without the security-hole inefficient broken eval-string solution" when I saw the first post. So, I didn't post my warning. Looks like I should have done it this time, and I'll have to do so next time. {sigh}

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

        Randal,

        I have read your standard disclaimer, and it makes no reference to what you mean when you call people fools. So my question to you is: What did you mean when you called me a fool?

        I can see it as nothing else other than a personal attack, which your standard disclaimer states that you never do. After re-reading your post, you are still calling me a fool.

        This forum is a fun place to find multiple ways to solve coding problems, most of which shouldn't be considered production safe. I don't feel the need to defend any solutions I present to you, or to make sure they don't violate any of your pet peeves.

        On the other hand, I am a curious fellow, and would like to know why eval is a bad solution in this case. I read the post you linked to, which appeared to be a warning against eval without specifics. I understand that it is inefficient, but the solution I presented was self contained, and I do not see a method by which "`rm -rf /`" or something similar could be introduced.

        Eagerly awaiting your reply,
        Curtis

Re: hash problem
by demerphq (Chancellor) on Jul 19, 2004 at 18:23 UTC

    The only reason I'm replying to this node (its a commonly asked question and has been answered many times) is that there is a tendency to go for "cute" solutions that frankly don't generalize well. If we consider your question literally then the code provided by BrowserUk, dave_the_m and sacked all work fine. However if we dare to think outside the box a little and guess that you may want to do this in such a way that you add to the tree each time then their solutions are not viable. They clobber the tree as they build so they are not useful for repeated use on the same tree. Assuming you were looking for such code perhaps the following (not entirely elegant) solution may be more appropriate:

    use strict; use warnings; use Data::Dumper; sub add_to_hash { my $hash=my $root=(ref $_[0] ? shift : {}); my $last=pop; for my $key (@_) { $hash=($hash->{$key}||={}); die "Eeek, not a ref!" unless ref $hash; } $hash->{$last}=1; return $root; } my %hash; add_to_hash(\%hash,qw(a b c d)); add_to_hash(\%hash,qw(a c d e)); print Dumper(\%hash);

    HTH


    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi


      Seconded.

      If you'd prefer not to roll your own, I've got a similar function in my Data::DRef module on CPAN:

      use Data::Dref qw( set_value_for_keys ); my %hash; set_value_for_keys( \%hash, 1, qw(a b c d) ); set_value_for_keys( \%hash, 1, qw(a c d e) );

      There's also a corresponding get_value_for_keys function, if needed...

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (2)
As of 2025-03-20 18:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When you first encountered Perl, which feature amazed you the most?










    Results (61 votes). Check out past polls.