Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Declare and slice-initialize hash in one statement?

by chester (Hermit)
on Oct 27, 2005 at 16:10 UTC ( #503393=perlquestion: print w/ replies, xml ) Need Help??
chester has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

Super Search has failed me. Is there a way to declare a hash and slice-initialize it in one statement, under use strict? I'm guessing it's going to be nasty-looking code if it's even possible, so whether I use it is debatable, but it's one of those "It might be possible, I just can't think how!" kinds of things I've always been curious about.

use strict; my @keys = (1..3); my @values = (4..6); my %hash; @hash{@keys} = @values; # works, but two statements # my %hash{@keys} = @values; I wished this worked, but syntax error # my @hash{@keys} = @values; Also syntax error # my $hash{@keys} = @values; Clearly wrong, and dumb (and syntax erro +r) my %hash = map {$keys[$_] => $values[$_]} (0..$#keys); # Far too long- +winded no strict; @hash{@keys} = @values; # works, but ew

Comment on Declare and slice-initialize hash in one statement?
Select or Download Code
Re: Declare and slice-initialize hash in one statement?
by davido (Archbishop) on Oct 27, 2005 at 16:14 UTC

    Your map solution is as close as you'll come, but you're right, if all you want to do is initialize a slice it's too longwinded.

    You cannot declare a hash, and initialize a slice at the same time. Just do it this way:

    my %hash; @hash{ list of keys } = ( list of values );

    ...where list of keys and list of values are obviously left up to you to fill in the blanks. BTW: Don't do the "no strict" method. Here's why. That version results in %hash being created as a package global, instead of as a lexical, and there is a big difference.


    Dave

      Note that the creation of the package hash isn't due to the absense of 'use strict', but the absense of a 'my' keyword.
      use strict; @::hash{@keys} = @values;
      creates a package hash as well.
      Perl --((8:>*
Re: Declare and slice-initialize hash in one statement?
by japhy (Canon) on Oct 27, 2005 at 16:31 UTC
      I never would've thought of that. Very nice. (Now I need to forget I ever saw it, lest I'm tempted to use it someday.)
Re: Declare and slice-initialize hash in one statement?
by BrowserUk (Pope) on Oct 27, 2005 at 16:31 UTC

    You could use this

    Update: Corrected typo (s/0/$_/)

    sub zip { map{ $_[0][$_], $_[1][$_] } 0 .. $#{$_[0]} } my %hash = zip [ 1 .. 3 ], [ 'a' .. 'c' ]; my @a = 1 .. 3; my @b = 'a' .. 'c'; my %hash = zip \@a, \@b;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Which is also available in List::MoreUtils, with no referencing needed.

      use strict; use List::MoreUtils qw(zip); my @keys = (1..3); my @values = (4..6); my %hash = zip @keys, @values;

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

        Also called mesh()

        The downside of it's use of prototypes is that it precludes the use of inline anonymous array constructors:

        use List::MoreUtils qw[zip]; my %hash = zip [1..3],['a'..'c']; Type of arg 1 to main::zip must be array (not single ref constructor) +at Type of arg 2 to main::zip must be array (not single ref constructor) +at

        In this case, trading the avoidance of two backslashes for the need to declare and initilise temporary arrays, or substitute the unweildy

        use List::MoreUtils qw[zip]; my %hash = zip @{[1..3]},@{['a'..'c']};

        is not such a good trade. Of course it does handle more than two arrays, but that is a fairly rare usage.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

      Perl 6 changes:

      • zip is built in!.
      • There is an infix operator for zipping too: ¥.
      • The ASCII equivalent, if you can't or won't type ¥, is: Y.
      • zip doesn't take references, but multiple lists. These are separated by semicolons (within parens!), or are specified with multiple <== pipes.
      • Lists can be initialized with a list of pairs, but fashioned key/value lists still work.
      Examples:
      my %hash = zip(@keys; @values); my %hash = zip(<== @keys <== @values); my %hash = @keys @values; my %hash = @keys Y @values;

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2014-10-22 00:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (112 votes), past polls