On Oct 30, Robert Thompson said:
> Another question though, is there a simple way to uniq an array,
>ie search through it and removing all duplicates? Up until now I have
>been making a clumsy subroutine to do this, but I am wondering if there
>is something more simple that will handle this.
That's a very common question -- as such, it can be found in the
FAQ. There are many ways to approach this problem. If you want to keep
your elements in the same order, a grep() will work for you:
{
my %seen;
@uniq = grep !$seen{$_}++, @orig;
}
Let's break this down into a for loop:
for (@orig) {
if (!$seen{$_}++) {
push @uniq, $_;
}
}
The only tricky part of this code is the !$seen{$_}++. What is it
doing? Well, first, it checks to see if $seen{$_} is false (that's the
!$seen{$_} part). If it IS false, the if block is executed. If it's not
false, there's no else block.
What does $seen{$_} being false indicate? Well, we've given the hash a
rather apropos name, "seen". This hash indicates whether or not we've
seen this array element before. That's where the ++ part comes in. If ++
comes AFTER a variable, the incrementing is done AFTER the value of the
variable is returned:
$x = 10;
$y = $x++;
# $x is 11, $y is 10
So let's look at the if statement again:
if (! $seen{$_}++) { ... }
First, $seen{$_} is tested for falsehood. AFTER THAT TEST RETURNS,
$seen{$_} is then incremented. Let's make a table of what happens to
$seen{$_} for some $_:
$seen{foo} !$seen{foo} after $seen{foo}++
0 1 1
1 0 2
2 0 3
: 0 :
So what happens is, if we haven't seen a specific element before, we add
it to the array. Otherwise, we do nothing, and either way, we make a note
that we've seen the element. All that is expressed in the rather compact
code:
@uniq = grep !$seen{$_}++, @orig;
--
Jeff "japhy" Pinyan [EMAIL PROTECTED] http://www.pobox.com/~japhy/
RPI Acacia brother #734 http://www.perlmonks.org/ http://www.cpan.org/
** Look for "Regular Expressions in Perl" published by Manning, in 2002 **
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]