Steve Bertrand wrote:
> > Steve Bertrand wrote:
> > > I got it...
> > > 
> > > for my $item (@clean) {
> > >         if (! grep ($_ eq $item, @array)) {
> > >                 push (@array, $item);
> > >                 print "$item\n";
> > >         }
> > > }
> > 
> > FWIW, this is a FAQ (see "perldoc -q duplicate"). If the array
> > elements can be compared with string semantics (as you are doing
> > here), the following will work:
> > 
> >    my @array = do { my %seen; grep !$seen{$_}++, @clean };
> 
> Thank you for the info...but pardon my ignorance. I'd just like to
> understand what is happening there. Is grep adding to the array the
> keys in the hash that have values that have not been incremented?

Erm, sort of...

grep() is a function that returns a list. Since it's the last expression
evaluated in the do { } block, that list becomes the result assigned to
@array.

grep() takes an input list (the elements of @clean) and returns a list
composed of each element from @clean for which the following expression is
true:

   !$seen{$_}++

Within the expression $_ represents the current element of @clean being
examined. What's happening is that the hash entry $seen{$_} is being
incremented by one. The value of the expression is the hash entry $seen{$_}
BEFORE incrementing.

So, for any given string coming from @clean, the hash entry $seen{$_} will
be undef the first time, and then 1 the second time, 2 the third time, and
so on. The ! operator logically negates the value, so the entire expression
returns the following pattern for a repeated series of the same value:

   true, false, false, false, ...

In other words, the expression is true only for the first occurence of each
different entry in @clean. Since grep() only passes through the elements for
which the expression is "true", only the first occurence of each different
entry in @clean makes it into @array, thus "removing" the duplicates, QED.

The do { } block is there because we need a temporary hash. The hash goes
away at the end of the do { } block since we don't need it after grep() is
finished.

n.b. there's another way you can do this:

   @array = do { my %h; @[EMAIL PROTECTED] = (); keys %h };

or similarly,

   @array = keys %{{map +($_, 1), @clean}};

These do not preserve the order of the values in @clean however.

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to