Win has asked for the wisdom of the Perl Monks concerning the following question:

Please could somebody put the following line into English.
next if $seen{ $elem }++;
in the code:
my %hash = map { $_, 1 } @array; # or a hash slice: @hash{ @array } = (); # or a foreach: $hash{$_} = 1 foreach ( @array ); my @unique = keys %hash; my @unique = (); my %seen = (); foreach my $elem ( @array ) { next if $seen{ $elem }++; push @unique, $elem; }
My attempt is:

Insert $elem into the hash 'seen' and skip to the next loop event if this $elem is already present in the hash 'seen'.

I realise that my attempt is not quite there.

Replies are listed 'Best First'.
Re: What does 'next if $hash{$elem}++;' mean?
by dragonchild (Archbishop) on Feb 17, 2006 at 15:32 UTC
    1. If a key doesn't exist in a hashref before it's used, it's created for you automatically. This is called autovivification.
    2. The postfix increment operator (++) will increment the value of the thing it's after, then return the old value.
    3. next will skip to the next iteration of the loop.

    So, this code will skip to the next iteration of the loop if it's already seen that element. Just as if you'd read the code out loud. :-)


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: What does 'next if $hash{$elem}++;' mean?
by blazar (Canon) on Feb 17, 2006 at 17:52 UTC
    Please could somebody put the following line into English.
    next if $seen{ $elem }++;

    [snip]

    My attempt is:
    Insert $elem into the hash 'seen' and skip to the next loop event if this $elem is already present in the hash 'seen'.

    How 'bout exectly the way you read it, i.e. "skip to the next iteration of the loop if you have already seen $elem"? That is "if the counter associated to $elem (that is the value of the hash %seen on the key $elem), which you're (post-)incrementing (++) at this iteration too, is greater than zero".

    Was there anything particular difficult to understand in this reply?

Re: What does 'next if $hash{$elem}++;' mean?
by radiantmatrix (Parson) on Feb 17, 2006 at 19:24 UTC

    next if $seen{ $elem }++;

    "Skip to the next iteration of the loop if $seen{ $elem } is true, otherwise make $seen{ $elem } true and continue."

    Check out the segment on the unary '++' operator in perlop. When the operator follows a variable, it is incremented after its evaluation. In other words, in the above code, if checks the value of $seen{ $elem } before incrementing it. Since the action "next" is taken before the increment happens, the increment is skipped. Here's longer (and probably slightly slower) equivalent code:

    if ( $seen{ $elem } ) { next; # skip to the next loop iteration } else { $seen{ $elem } += 1; }

    This is a common pattern that checks if you've encountered $elem before. If you have, it will not process it a second time; otherwise, it will mark $elem so that you won't process it again.

    This could be used to get all the unique lines from a file, for example.

    use strict; use warnings; open my $IN, '<', $ARGV[0] or die("Can't read $ARGV[0]: $!"); open my $OUT, '<', $ARGV[1] or die("Can't write $ARGV[1]: $!"); my %seen; while (<$IN>) { next if $seen{$_}++; # check/mark line as seen print $OUT $_; } close $IN; close $OUT;

    Or, even shorter while loop:

    while (<$IN>) { $seen{$_}++ || print $OUT $_ }
    <-radiant.matrix->
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    I haven't found a problem yet that can't be solved by a well-placed trebuchet