### Hash slices ?

by ChOas (Curate)
 on Dec 01, 2000 at 15:27 UTC Need Help??
ChOas has asked for the wisdom of the Perl Monks concerning the following question:

This results from a discussion in the chatterbox
Please help me on this one, can someone explain to
me the result of the following code:
```#!/usr/bin/perl -w
use strict;

my @keys = qw(one two three);
my %hash = ( four => 4, five => 5, six => 6);
print "@keys\n";
if (@hash{@keys}) {
print "yep\n";
} else {
print "nope\n";
}

push @keys, 'four';

print "@keys\n";
if (@hash{@keys}) {
print "yep\n";
} else {
print "nope\n";
}

@keys = qw(one two three);
unshift @keys,'four';
print "@keys\n";
if (@hash{@keys}) {
print "yep\n";
} else {
print "nope\n";
}

Result:
martijn@xxxx\$ ./test
one two three
nope
one two three four
yep
four one two three
nope

Strange innit ?

Replies are listed 'Best First'.
Re: Hash slices ?
by kilinrax (Deacon) on Dec 01, 2000 at 17:30 UTC
Adding a couple more tests to your script gives us a clue:
```@keys = qw(one two five);
unshift @keys,'four';
print "@keys\n";
if (@hash{@keys}) {
print "yep\n";
} else {
print "nope\n";
}

@keys = qw(one two five);
push @keys, 'two';
print "@keys\n";
if (@hash{@keys}) {
print "yep\n";
} else {
print "nope\n";
}
Gives the result:
```four one two five
yep
one two five two
nope
It would appear that only the presence of the last key in the array is affecting whether the test returns true or false.

I would suggest a possible solution would be to abuse grep, thus:
```if ( grep{ exists( \$hash{\$_} ) } @keys ) {
print "yep\n";
} else {
print "nope\n";
}
Ayup -- it's the last key that matters, just as if the hash slice were being treated as a list -- evaluate a list in a scalar context and it returns the last value.

There's nothing in the docs that I could find that says that a hash slice would be interpreted as a list rather than a proper array, but it does apear to be the case.

Any one further investigation, it seems that my original solution suffered from a fundamental problem.

```my %hash = (one => 1, two => 2, three => 3);
my @keys = qw(four five six);
my @slice = @hash{@keys};

@slice is now contains four undef elements, where I thought it would be an empty list (don't know why I thought that - it was very early in the morning.

If the hash slice was interpreted as an array, it would therefore always be true and therefore doesn't solve ChOas' original problem. That would be better addressed using something like:

```if (grep { exists %hash{\$_} } @keys) {
print "yep\n";
} else {
print "nope\n";
}
--
<http://www.dave.org.uk>

"Perl makes the fun jobs fun
and the boring jobs bearable" - me

Well, we always go around about this, because the perldata does clearly say:
```           @days               # (\$days[0], \$days[1],... \$days[n])
@days[3,4,5]        # same as @days[3..5]
@days{'a','c'}      # same as (\$days{'a'},\$days{'c'})
See the "same as"? That's the operative words. To make it the same, it has to return the last element of the list in a scalar context. So yes, the behavior is documented, and derivable from the docs.
Re: Hash slices ?
by ChOas (Curate) on Dec 01, 2000 at 15:38 UTC
The original discussion for this one
started with my question: how do I find if
at least one of many keys in a list is in a hash
(quick, fast, and simple)
davorg offered me a working example, but when I
tried it, I inserted the 'four' at the start of the list
which didn't work
The push on the other hand DID.
and as you can see the unshift doesn't work either

Many thanks davorg !!
Let's see what people can tell us about this one ;))

how do I find if at least one of many keys in a list is in a hash (quick, fast, and simple)

Dunno if this meets *all* of your criteria, but I find this simple enough:

```my @search_keys = qw(one two three);
my %hash = ( four=>4,
five=>5,
six=>6);
my \$foundit =0;
foreach (@search_keys) {
if (exists \$hash{\$_}) {
\$foundit =1;
print "found an entry for \$_ in %hash!\n";
}
}

Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Given that the idea is to find out if any of the keys exist in the hash, it would be more efficient to call last and exit the loop once you've found one.

--
<http://www.dave.org.uk>

"Perl makes the fun jobs fun
and the boring jobs bearable" - me

Create A New User
Node Status?
node history
Node Type: perlquestion [id://44328]
Approved by root
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (7)
As of 2018-04-23 12:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (84 votes). Check out past polls.

Notices?