views:

4824

answers:

4

I'm pushing elements into an array during a while statement. Each element is a teacher's name. There ends up being duplicate teacher names in the array when the loop finishes. Sometimes they are not right next to each other in the array, sometimes they are.

How can I print only the unique values in that array after its finished getting values pushed into it? Without having to parse the entire array each time I want to print an element.

Heres the code after everything has been pushed into the array:

$faculty_len = @faculty;
$i=0;
while ($i != $faculty_len)
{
     printf $fh '"'.$faculty[$i].'"';
     $i++;
}
+7  A: 

I suggest pushing it into a hash. like this:

my %faculty_hash = ();
foreach my $facs (@faculty) {
  $faculty_hash{$facs} = 1;
}
my @faculty_unique = keys(%faculty_hash);
This can sometimes change the order of the elements. Perhaps you could mention the possibility of putting "push @faculty_unique, $facs unless exists $faculty_hash{$facs}" inside the for-loop.
A. Rex
I figured for teacher's name, order wasn't critical.If it is, it's probably alphabetical. Still not too hard to solve.
You can always "sort keys %faculty_hash" to get a sorted (ASCII-betically) list.
Max Lybbert
instead of using a foreach, i'd use map: my %faculty_hash = map { $_ => 1 } @faculty;
Robert P
+6  A: 

Keeping uniques is the same thing as eliminating duplicates, see this equivalent question: http://stackoverflow.com/questions/7651/how-do-i-remove-duplicate-items-from-an-array-in-perl

Adam Bellaire
+12  A: 
use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}
innaM
This works if installing MoreUtils is possible. It's not always.
Robert P
List::MoreUtils is a single module with no dependencies. You should be able to have a local copy of that module if you are on shared hosting
innaM
+4  A: 

Your best bet would be to use a (basically) built-in tool, like uniq (as described by Manni).

If you don't have the ability to use uniq and want to preserve order, you can use grep to simulate that.

my %seen;
my @unique = grep { ! $seen{$_}++ } @faculty;
# printing, etc.

This first gives you a hash where each key is each entry. Then, you iterate over each element, counting how many of them there are, and adding the first one. (Updated with comments by brian d foy)

Robert P
I think you really just mean this:my %Seen;@unique = grep { ! $Seen{$_}++ } @faculty;
brian d foy
Ah, of course! Updating.
Robert P