in reply to removing duplicates from an array of hashes

As TMTWTDI, I'll add an inplace version:
my %seen; for my $i (reverse (0 .. @$ref-1)) { # replaces current item in array with last item # and removes the last element if id already seen $ref->[$i] = pop @$ref if $seen{$ref->[$i]->{id}}++; }
Note: Ordering in the array might change

Update: inplace version that keeps the ordering

my %seen; my $removed = 0; for my $i (0 .. @$ref-1) { my $item = $ref->[$i]; $seen{$item->{id}}++ ? $removed++ : ($ref->[$i-$removed] = $item); } splice @$ref,-$removed;

Greetings,
Janek Schleicher

Replies are listed 'Best First'.
Re^2: removing duplicates from an array of hashes
by AnomalousMonk (Archbishop) on Apr 17, 2014 at 17:32 UTC

    Just a matter of idle curiosity... I notice you use  @$ref-1 instead of  $#$ref for obtaining the max array index. Why do you prefer this? If  $[ were ever changed (but don't do that!),  @$ref-1 would yield an incorrect value for max index. (Although I suppose that one could argue that to be $[-safe, one ought always to iterate over  $[ .. $#array rather than  0 .. $#array to safely visit the entire range of  @array indices.)

    Also, in your second code example
        splice @$ref,-$removed;
    might be written as the (presumably) marginally faster
        $#$ref -= $removed;

    Update: I should make it clear that this post was prompted mainly by the non-idiomatic nature of the  @$ref-1 expression. Any "lack-of-safety" issue is only a kind of cayenne pepper icing on the cake.

      Reasoning is simple:

      I didn't program for a long time (close to 10yrs), I still were sure that $#array is the last item, but I was too lazy to look up, how to note it when it is a $arrayref, so I just took 0..@$arrayref-1 what works same here and for at least where I stopped, it was same idiomatic. Every programmer in the world understand 0..length(array)-1 in a heartbeat, only Perl cracks will understand $[..$#array.

      I wasn't aware that I could just $#array -= $n to make the array smaller. To be honest, I'm not sure whether I'd like it. It works only in so rare cases where we basical want to  pop @array, $n and don't care about what were the last items. splice is a clear idiom that we intend to remove entries out of an array and then specify which. If the special case were more often, o.k., but how often do we even use splice? IMHO that is even rare, most of the time we pop, shift or slice with @array[4..7,11..13] and so on, so no need to trick us selfs just to trick us. Code should be easy.

      Anyway, pretty to cool to have learned some new tricks in Perl :-)

      Greetings,
      Janek Schleicher