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!

Reply via email to