Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

removing duplicated elements from array, with a difference

by Anonymous Monk
on Aug 28, 2002 at 18:02 UTC ( #193522=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

hello monks, i'm a perl novice and would appreciate your help. I have an array containing duplicate elements that require removing from that array. However, I'd like both the duplicate and the original to both be removed. So for example, if the array contains two or more elements containing the letter 'X', then I would like all of those elements containing 'X' completely removed. Thanks, Paul

Comment on removing duplicated elements from array, with a difference
Re: removing duplicated elements from array, with a difference
by thelenm (Vicar) on Aug 28, 2002 at 18:07 UTC
    I'm not sure of a good one-pass approach for this (but perhaps there is one). Here's a two-pass approach, one pass to create the "count" hash and another pass to remove duplicate elements.
    $count{$_}++ for @array; @new_array = grep {$count{$_} < 2} @array;

    -- Mike

    --
    just,my${.02}

      Thanks for your help, but I've realised that I need to do the same problem except that the duplicate may be a particular pattern within an element. So therefore all those elements containing that pattern need to be removed. thanks again, paul
        I've realised that I need to do the same problem except that the duplicate may be a particular pattern within an element. So therefore all those elements containing that pattern need to be removed.

        You may have to explain this further. To find the elements not matching a particular pattern you can use something like:

        @without = grep { !/PATTERN/ } @original;

        I'm not sure that addresses the issue you are trying to describe with the phrase "the duplicate may be a particular pattern within an element."

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: removing duplicated elements from array, with a difference
by dpuu (Chaplain) on Aug 28, 2002 at 18:11 UTC
    A two-pass process. First, count number of entries for each elem:
    my %item_count; %item_count{$_}++ foreach (@array);
    Next, remove any element whose item_count != 1:
    @result = grep {$item_count{$_} == 1} @array;
    --Dave.

    Update: for the duplicate sub-pattern problem:

    my %item_count; %item_count{$_}++ for grep {/pattern/} @array @result = grep {$item_count{$_} <= 1} @array;

    Update 2: to avoid the uninitialized value warning:

    @result = grep {($item_count{$_}||0) <= 1} @array;
Re: removing duplicated elements from array, with a difference
by krujos (Curate) on Aug 28, 2002 at 18:21 UTC
    This is probably not the most efficient way to do this but it will work. This uses a hash to keep track of the duplicates.
    my %hash; my @NewArray; #read all of the values of the array into keys of the hash, #this eliminates all of the duplicates foreach my $var (@OriginalArray) { $hash{$var}=0; } #this loop marks any variable that appeared twice in the #original array. foreach my $var2 (@OriginalArray) { $hash{$var}++; } #This fills a new array based on the information from the #above loop foreach my $var3 (keys (%hash)) { if (!$hash{$var3} > 1) { print "$hash{$var3} deleted\n"; } else { $NewArray[@NewArray]=$hash{$var3}; } } @OriginalArray = @NewArray;
    update ++dpuu and thelenm for their much better and more efficient answers to this question.
Re: removing duplicated elements from array, with a difference
by BrowserUk (Pope) on Aug 28, 2002 at 18:34 UTC

    In one pass?? :^)

    my %count; my @deduped = grep { $count{$_} == 1 } map { $count{$_} ++; $_ } @data +;

    What's this about a "crooked mitre"? I'm good at woodwork!
      Well, that's still two passes, but it's one line, which gets a ++BrowserUk from me! :-)

      -- Mike

      --
      just,my${.02}

        Thanks for your help, but I've realised that I need to do the same problem except that the duplicate may be a particular pattern within an element. So therefore all those elements containing that pattern need to be removed. thanks again, paul
Re: removing duplicated elements from array, with a difference
by Aristotle (Chancellor) on Aug 28, 2002 at 19:45 UTC
    One and a half passes.
    my ($i, %seen) = (0); my @no_dup = grep { 2 < push @{$seen{/(pattern)/}}, $i++ } @with_dup; @no_dup = map { 2 < @$_ ? $no_dup[$_->[0]] : () } values %seen;
    Makes use of the little known return value from push but probably no more efficient than the two pass solutions due to creation of a lot of anonymous arrays. Hmm.. I can do better..
    my ($i, %seen) = (0); my @no_dup = grep { -1 != ($seen{/(pattern)/} = exists $seen{$1} ? -1 : $i++) } @with_dup; @no_dup = @no_dup{grep $_ != -1, values %seen};
    Update: fixed a thinko.

    Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://193522]
Approved by thelenm
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (8)
As of 2014-10-02 00:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    What is your favourite meta-syntactic variable name?














    Results (41 votes), past polls