Effective Perl by Joseph N. Hall

Observations and Tips from the author of Effective Perl Programming

Saturday, January 14, 2006

Idiomatic Perl: The Hash as a Set

It's often useful to know whether a particular element or value exists in a set of items. For example, you might want to know whether the color 'red' exists in a list of colors. If you have this list in an array, you have to iterate over the contents of the array with a loop:
my @color = qw(green blue yellow cyan violet puce taupe lilac);
for my $item @color (
if ($item eq 'red') {
print "Found red.\n";
exit;
}
}
print "Found no red.\n";
This isn't terribly exciting and it is horribly inefficient with larger arrays. The idiomatic way of looking for something in a set in Perl is seeing whether it exists in a hash:
# retaining @color from above
my %color;
for my $item (@color) {
$color{$item} = 1; # 1 or any "true" value
}

if ($color{'red'}) {
print "Red found!\n";
}
Here I loaded the hash %color with the items in the original array @color. The items themselves are the keys. The values are something "true" - it doesn't matter what, just as long as it's "true," so I use 1. Now, $color{$foo} is true if the hash %color contains the item $foo.

There's a succinct way to create the hash above:
my %color = map { $_, 1 } @color;
This is essentially the same as the for loop, but shorter and more idiomatic.

2 Comments:

At 1:23 AM, Anonymous Anonymous said...

Even sexier:

my @color = qw(red green blue);
my %color;

@color{@color} = (1) x @color;

if($color{red}) {
...
}

 
At 4:09 PM, Blogger Unknown said...

Found this typo in the first sample; line 2 is:

for my $item (

which fails; but this change makes it work for me:

for my $item (@color) {

 

Post a Comment

<< Home