In Perl, how do I create a hash whose keys come from a given array?

后端 未结 14 688
你的背包
你的背包 2021-01-29 19:53

Let\'s say I have an array, and I know I\'m going to be doing a lot of \"Does the array contain X?\" checks. The efficient way to do this is to turn that array into a hash, wher

相关标签:
14条回答
  • 2021-01-29 20:23
    #!/usr/bin/perl -w
    
    use strict;
    use Data::Dumper;
    
    my @a = qw(5 8 2 5 4 8 9);
    my @b = qw(7 6 5 4 3 2 1);
    my $h = {};
    
    @{$h}{@a} = @b;
    
    print Dumper($h);
    

    gives (note repeated keys get the value at the greatest position in the array - ie 8->2 and not 6)

    $VAR1 = {
              '8' => '2',
              '4' => '3',
              '9' => '1',
              '2' => '5',
              '5' => '4'
            };
    
    0 讨论(0)
  • 2021-01-29 20:25
     @hash{@array} = (1) x @array;
    

    It's a hash slice, a list of values from the hash, so it gets the list-y @ in front.

    From the docs:

    If you're confused about why you use an '@' there on a hash slice instead of a '%', think of it like this. The type of bracket (square or curly) governs whether it's an array or a hash being looked at. On the other hand, the leading symbol ('$' or '@') on the array or hash indicates whether you are getting back a singular value (a scalar) or a plural one (a list).

    0 讨论(0)
  • 2021-01-29 20:25

    Note that if typing if ( exists $hash{ key } ) isn’t too much work for you (which I prefer to use since the matter of interest is really the presence of a key rather than the truthiness of its value), then you can use the short and sweet

    @hash{@key} = ();
    
    0 讨论(0)
  • 2021-01-29 20:25

    If you do a lot of set theoretic operations - you can also use Set::Scalar or similar module. Then $s = Set::Scalar->new( @array ) will build the Set for you - and you can query it with: $s->contains($m).

    0 讨论(0)
  • 2021-01-29 20:26

    In perl 5.10, there's the close-to-magic ~~ operator:

    sub invite_in {
        my $vampires = [ qw(Angel Darla Spike Drusilla) ];
        return ($_[0] ~~ $vampires) ? 0 : 1 ;
    }
    

    See here: http://dev.perl.org/perl5/news/2007/perl-5.10.0.html

    0 讨论(0)
  • 2021-01-29 20:30

    Raldi's solution can be tightened up to this (the '=>' from the original is not necessary):

    my %hash = map { $_,1 } @array;
    

    This technique can also be used for turning text lists into hashes:

    my %hash = map { $_,1 } split(",",$line)
    

    Additionally if you have a line of values like this: "foo=1,bar=2,baz=3" you can do this:

    my %hash = map { split("=",$_) } split(",",$line);
    

    [EDIT to include]


    Another solution offered (which takes two lines) is:

    my %hash;
    #The values in %hash can only be accessed by doing exists($hash{$key})
    #The assignment only works with '= undef;' and will not work properly with '= 1;'
    #if you do '= 1;' only the hash key of $array[0] will be set to 1;
    @hash{@array} = undef;
    
    0 讨论(0)
提交回复
热议问题