On 8/15/06, SFantar <[EMAIL PROTECTED]> wrote:
Xavier Noria a e'crit :
> In the example I sent before, we used a similar trick but using grep, > because we want to iterate over @array and filter duplicates out (you > need to know grep to understand this): > > %seen = (); > @uniq = grep { > my $is_new = 0; > if not exists $seen{$_} { > $seen{$_} = 1; > $is_new = 1; > } > $is_new; > } @array; > > That code is more explicit. We use a hash table called %seen to > register seen strings. The way to accomplish that is that we assign an > arbitrary value to $seen{john} the first time we encounter 'john', and > so subsequent calls to exists $seen{john} will return true. In those > cases $is_new remains 0 and grep filters that element out.
On the contrary, the code written above is not clear yet. What does your code do exactly when it comes to deal with smith, edward which appear twice in @array initially?
The key here is understanding that grep returns the elements from a list for which the expression you specify returns a true value. In most Perl contexts, that means "has a return value greater than 0". Also, in a grep block, $_ is reference to the current value from the list. Xavier's code boils down to: 1) if $seen{$_} doesn't exist, then we haven't seen this value before so a) create $seen{$_}, so it exists next time, and b) make $is_new =1, so it's true. 2) if $seen{$_} does exists, we have seen this value before, so a) don't do anything to %seen, and b) leave $is_new 0, so it's false 3) return $is_new. because of grep's true/false behavior, when $is_new == 1, $_ will be returned by grep and added to the @uniq array. When $is_new == 0, grep won't return $_, and nothing will be added to the array. Other common way to write this are: @unique = grep { $seen{$_}++, $seen{$_} == 1 ? 1 : 0 } @array; @unique = grep { $seen{$_}++, $seen{$_} == 1 ? $_ : undef } @array; Since grep only cares if the expression evaluates true or false, the $_ in second version is superfluous, but it may be the easiest to read and understand. If you want to find unique values and keep a count of how many times something has been seen, then you can do something like: $seen{$_}++ foreach @array; my @unique = keys %seen; while ( ($k, $v) = each %seen ) { print "$k was seen $v times\n"; } # or if you want them sorted foreach (sort @array) { print "$_ was seen $seen{$_} times\n"; } HTH, -- jay -------------------------------------------------- This email and attachment(s): [ ] blogable; [ x ] ask first; [ ] private and confidential daggerquill [at] gmail [dot] com http://www.tuaw.com http://www.dpguru.com http://www.engatiki.org values of β will give rise to dom!