Hello shankonit, and welcome to the Monastery!
The statement my %seen creates an empty hash. Then the foreach loop works as follows: On the first iteration, $element is 3 (the first element of the array @array). The if statement looks up the hash value $seen{$element}, i.e. $seen{3}, but of course doesn’t find it because the hash is empty. But the code says to increment (++) that element, so an important feature of Perl called autovivification comes into play: the hash element $seen{3} is created, with an initial value of undef, which is silently interpreted as 0 (zero) and incremented to 1. But because the postincrement form is used (i.e., $x++ instead of ++$x), the value of the expression $seen{$element}++ is the value it had before the increment, which in this case is undef. And since undef is false, negating this false value with not makes it true, so the if clause is entered and $element is pushed onto the array @ordered.
Likewise for the subsquent iterations in which $element is equal to 4 and then to 1. But when $element is set to 4 a second time, the expression $seen{$element} is already present in the hash, and has the value 1, which is true. Negating it makes it false, so the if clause is not entered. The result is that each element of @array is added only once to the new array @ordered.
The point of this is presumably to show how to convert an array with duplicates: @array = (3, 4, 1, 4, 7, 7, 4, 1, 3, 8); into an array with the same elements but all duplicates removed: @ordered = (3, 4, 1, 7, 8). Unfortunately, the new array is misnamed: it isn’t “ordered,” it is rather an array of unique values. The code has nothing to do with ordering, only with the removal of duplicate elements.
Update 1: On autovivification, see the references in this node. On removing duplicates from an array, see How-can-I-remove-duplicate-elements-from-a-list-or-array of perlfaq4.
Update 2: On second thoughts, I think the hash %unordered and array @ordered have been so-named to highlight an important difference between the first technique and the second: namely, that the second preserves the order of the first occurrences of each element in the original array, whereas the first technique does not (because hashes, unlike arrays, are unordered).
Hope that helps,
| [reply] [d/l] [select] |
The code shows two approaches to remove duplicates in @array .
The first @unordered approach is using a hash slice, and since hash keys are unique, duplicates are overwritten. But the original order is lost, since keys returns in random order.
The second @ordered approach rejects duplicates from copying, hence @ordered preserves the order of the first occurrences. This is done with %seen which postincrements the value per element
if( not $seen{$element}++ )
Only 0 is false, hence repeated (i.e. "unseen") elements are filtered out.
PS: As a side note:
A hash slice initializing undef values is better written as @unordered{@array}=() , assigning undef to the first element is misleading!
| [reply] [d/l] [select] |
A hash slice initializing undef values is better written as @unordered{@array}=() , assigning undef to the first element is misleading! [emphasis added]
IMHO, this statement is itself a bit misleading. The two forms of the statement are exactly equivalent! The effect of either () or undef as the RHS of the assignment is exactly the same because both are equivalent to lists of undef values of exactly the same length as the @array array. This slightly obscure point must be understood regardless of the assignment used, and neither assignment seems to me better suited to making this point.
Give a man a fish: <%-(-(-(-<
| [reply] [d/l] [select] |
Its misleading, because the next maintainer might think he can replace undef with 0 and bang!
| [reply] |
Just a side note: The OP does not really seem to be about "context" in Perl, which is a very particular idea. Please see Context tutorial for a discussion.
Give a man a fish: <%-(-(-(-<
| [reply] [d/l] |