in reply to Removing duplicates in Array of Array

Why the technology restriction?

There is something of a disjunction between your problem description and the title of your node. What is it that you actually want to achieve? Maybe you should fill us in on some of the bigger picture?

BTW, your sample could be better (for some definition of better) written as:

use strict; use warnings; my @array = (["1", "1", "3"], ["1", "5", "6"], ["1", "1", "3"]); my @unique; my %seen; $seen{$_}++ or push @unique, $_ for @array; print "$_->[0] $_->[1] $_->[2]\n" for @unique;

although @unique is only required if order is important.

Oh, and your array initialization is completely broken. At the very least you should use the form I've shown above.


Perl reduces RSI - it saves typing

Replies are listed 'Best First'.
Re^2: Removing duplicates in Array of Array
by iphony (Acolyte) on Sep 04, 2008 at 04:40 UTC
    The sad story is I have a piece of code that can remove duplicates using grep:
    my @unique_terminal_id = grep { !($seen_values{$_->[4]}++) } @temp_ope +n_single; my %seen_values; my @unique_manufacturer_model = grep { !($seen_values{$_->[9]}{$_->[10 +]}++) } @unique_terminal_id; my %seen_values; my @unique_manufacturer_model_version = grep { !($seen_values{$_->[9]} +{$_->[10]}{$_->[11]}++) } @unique_terminal_id;
    But I discover that updating @unique_manufacturer_model also changes @unique_manufacturer_model_version. I was told that this is due to the fact that I am storing reference (cross-referencing trap). I was told to use Storeable(dclone), but I ca'nt figure out how to apply. So I was thinking if there could be a longer (inefficient) way of getting around this.

      Ah, so the bigger picture is that you need a deep copy of the elements from the original array? That is, at present you fall foul of:

      use strict; use warnings; my %seen; my @array = (["1", "1", "3"], ["1", "5", "6"], ["1", "1", "3"]); my @unique = grep {! $seen{$_->[1]}++} @array; print "@$_\n" for @array; print "\n"; map {$_++} @$_ for @unique; print "@$_\n" for @array; print "\n";

      Prints:

      1 1 3 1 5 6 1 1 3 2 2 4 2 6 7 1 1 3

      where you wanted @array unaffected by the manipulation of the contents of @unique. If you know that you are dealing with an AoA then you can:

      use strict; use warnings; my %seen; my @array = (["1", "1", "3"], ["1", "5", "6"], ["1", "1", "3"]); my @unique = map {[@$_]} grep {! $seen{$_->[1]}++} @array; print "@$_\n" for @array; print "\n"; map {$_++} @$_ for @unique; print "@$_\n" for @array; print "\n"; print "@$_\n" for @unique; print "\n";

      Prints:

      1 1 3 1 5 6 1 1 3 1 1 3 1 5 6 1 1 3 2 2 4 2 6 7

      Note the map used with the result from grep to copy the elements of each unique row? So actually rather than using neither grep nor map, what you really needed was to use both grep and map!


      Perl reduces RSI - it saves typing

        ... or just the map (no golf; grep was excessive) ...

        my @unique = map { ! $seen{ $_->[1] }++ ? [ @{ $_ } ] : () } @array;
        Hey GrandFather, thanks for your help. Using Map together with Grep does the trick. Thanks so much for your help. You are really the GrandFather of Perl...