in reply to explain use of increment operator in grep
%seen = ( paul => 1, jane => 1, betty => 1, );
The values in the hash aren't very important; the idea is that you can get the keys very easily:
print for keys %seen; # will print paul, jane, betty (though not necessarily in this order, +see note below)
Now, suppose I come and try to insert an element into %seen for which a key already exists. For example, I do
$seen{paul} = 1; # this does absolutely nothing! but... ++$seen{paul}; # paul's *value* is 2 now print for keys %seen; # yet this still prints the same list
The one-liner you're asking about uses this trick. The grep only passes keys in a hash for which the corresponing values is "< 2", but the increment is done before the lesser-than comparison. That is, the first time a particular key is encountered, $thatkey => 1 is effectively put into the hash.
Every subsequent visit with a particular key will cause the value to rise by one, but that also means the condition "< 2" will fail. So the effect is that duplicates are thrown away. A side effect of this technique is that %seen (or %temp, to use your name for it) holds the count of actually seen repetitions for each key!
Note that hashes in Perl are unordered, so that a simple "print keys" does not preserve the original relative order of elements. However, the code you brought does preserve ordering because the grep goes through elements of the original list one by one in order.
Golf note:
@list = grep !$temp{$_}++, @list; # same thing, shorter.
Update: fixed logic bug in last line. Thanks, Anonymonk.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: explain use of increment operator in grep
by Anonymous Monk on Mar 31, 2006 at 00:51 UTC | |
by gaal (Parson) on Mar 31, 2006 at 06:32 UTC |