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

I have an array that has multiple entries of the same element in it. I want to make a new array with just the unique elements in it. How can this be done? Also, if I am taking input into my script from the shell with
while (<>){ .... }
how do I account for multiple lines of input into an array or has? In other words, I want to distinguish between lines of input, but I do not know how to get Perl to input one line (carriage return) then another line and etc.

Replies are listed 'Best First'.
Re: Deciding unique elements of an array
by jarich (Curate) on Nov 15, 2001 at 08:25 UTC
    For the first point, like all things, there is more than one way to do it. Typically I'd use a hash, for example I'd do:
    #!/usr/bin/perl -w use strict; my @dup_array = qw/this this array has has duplicates/; my @unique_array; my %uniques; foreach my $elem (@dup_array) { push @unique_array, $elem unless $unique{$elem}++; } print "Unique elements are @unique_array";
    For the second problem, I think that you want to write something like
    my @lines = <>;
    Using <> in a list context gives you every line of input as an element of your array. That is $line[0] is your first line of code.

    Mind you, what a line of input is depends on whether you've messed around with $/;

Re: Deciding unique elements of an array
by FoxtrotUniform (Prior) on Nov 15, 2001 at 08:21 UTC

    I have an array that has multiple entries of the same element in it. I want to make a new array with just the unique elements in it. How can this be done?

    Pretty much every time you see the word "unique" in a problem, you want a hash. For this, I'd take a two-pass approach: tally the elements of the array, then pick out the unique ones. So:

    my %elem_count = (); for my $elem (@array) { $elem_count{$elem}++; } my @uniques = (); for my $elem (keys %elem_count) { push @uniques, $elem if $elem_count{$elem} == 1; }

    So (to be brutally obvious) we're storing the number of times we see each element in the hash %elem_count, then going through %elem_count key by key, picking out the ones that have a count of 1. (Of course, you can do the first bit at the same time as you're inserting elements in the array, which may or may not be practical.)

    As for your second question, I confess I don't really see the problem. Unless you've been mucking around with $/, $_ will contain the line you just read in at every pass through the while.

    --
    :wq

      You have a strange definition of unique :) ... your code removes any entries which don't occur exactly once, try for example this:

      my @array = qw/one one two/; # your algorithm print @uniques; # prints 'two' # and I would expect 'onetwo'

      So changing that and putting it a bit shorter:

      my %count = (); my @uniques = grep {! $count{$_}++} @array;

      ... and btw this should be in the FAQs somewhere.

      -- Hofmator

        You have a strange definition of unique :) ... your code removes any entries which don't occur exactly once

        Oh, I don't know, I like my definition. :-) I read (misread?) the question as "pick out the elements that occur just once" rather than "make a copy of the list with duplicate elements removed".

        ... and btw this should be in the FAQs somewhere.

        I believe it is, as mentioned in an earlier response.

        --
        :wq
Re: Deciding unique elements of an array
by Chrisf (Friar) on Nov 15, 2001 at 08:19 UTC
    I did a quick search and came up with This it should answer your question (check Super Search next time first :)
Re: Deciding unique elements of an array
by dvergin (Monsignor) on Nov 15, 2001 at 11:01 UTC
    How about...
    use strict; # Set up my @dups_ary = qw(a b c b d e f c b g h); # Do it my %temp_hash; undef @temp_hash{@dups_ary}; my @unique_ary = keys %temp_hash; # Prove it print "@unique_ary\n";
Re: Deciding unique elements of an array
by japhy (Canon) on Nov 15, 2001 at 11:11 UTC
    Going to CPAN soon (as soon as I get my JAPHY namespace) will be Tie::Array::Unique which does all the hard work for you.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Deciding unique elements of an array
by Sinister (Friar) on Nov 15, 2001 at 14:43 UTC
    Tsk,

    Using a hash to create a unique array!

    @array_thing = sort @array_thing; foreach (@array_thing) { push @unique if $_ ne $prev; $prev = $_; }
    Could it be more simple...?

    Sinister greetings.
    "With tying hashes you can do everything God and Larry have forbidden" -- Johan Vromans - YAPC::Europe 2001
    perldoc -q $_
      more simple - well.... yes and no...
      #!/usr/bin/perl my @a = ('a', 'b', 'c', 'c' ,'f', 'a', 'd'); my @b = grep (!$_{$_}++, @a);

      the 'my @b' line is the solution - it comes up with the correct info, but does involve doing a little work to get to the answer.

      It's definitely more simple to write :) but as for processing times etc - I really don't know if it's going to be better or not.

      It's a bit nasty to put this in your code without commenting it also, as I've got a few perl friends (none uber perl ppls, but 'know' perl), and none of them understood the intent :)