4

I'm trying to create an unique array regardless of its original order and using no module, this's what I've come up with so far:

my @arr = qw(b a a c d g e f);
my %hash;
@hash{@arr}=();
say keys %hash;
Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
bolbol
  • 325
  • 3
  • 9

3 Answers3

6

Yes. Since hash keys are unique, this is one idiomatic way to do it. The number of ways to accomplish the same thing are many.

You may also use a module, such as List::MoreUtils

use strict;
use warnings;

use List::MoreUtils qw(uniq);
print join ":", uniq qw(a a a b b c d);

Output:

a:b:c:d

Some different ways to dedupe:

my @arr = keys { map { $_ => 1 } qw(b a a c d g e f) };

The curly braces creates an anonymous hash for keys, the map statement creates a list of key/value pairs.


my @arr = dedupe(qw(a a b c d d e));

sub dedupe {
    my %hash = map { $_ => 1 } @_;
    return keys %hash;
}

Same thing, but in subroutine form, and split into two lines. Note that both lists will be in a semi-random order, since hashes are unordered.

The subroutine used by List::MoreUtils is equally simple, and perhaps preferable, since it will preserve the order of arguments. It still uses a hash, though.

sub uniq {
    my %seen = ();
    grep { not $seen{$_}++ } @_;
}
TLP
  • 66,756
  • 10
  • 92
  • 149
  • Thank you, I just figured instead of assigning 1 or `undef` to its values, we could give each key its associated array position like this: `@hash{@arr}=(0..$#arr);` then by swapping keys and values in `%hash` we can retrieve the values based on their original order, am I correct? – bolbol Jun 22 '12 at 06:22
  • 2
    Yes, you could do `my @arr = sort { $hash{$a} <=> $hash{$b} } keys %hash`. However, the `uniq` sub described above is preferable, since sorting is just extra processing. – TLP Jun 22 '12 at 06:25
  • @loldop You can use a hash ref with the `keys` function. Not sure which perl version is required. – TLP May 19 '13 at 15:07
  • @TLP, my old perl 5.12.4 can't do it :\ – gaussblurinc May 19 '13 at 15:50
2

Yes you are using the correct way but there are many other ways as well to create a unique array.

see perlfaq4: How can I remove duplicate elements from a list or array? for more details.

Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
1

A unique array with no ordering a.k.a. a set. I know you said 'no module' (why?!). But if you change your mind, try Set::Object or Set::Scalar

Staugaard
  • 1,077
  • 7
  • 5
  • Thanks, because my intention is to understand the concept and not solving a problem, otherwise I have no problem with using modules. – bolbol Jun 22 '12 at 06:51