Suppose you have a hash:

%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.


In reply to Re: explain use of increment operator in grep by gaal
in thread explain use of increment operator in grep by pglenski

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.