I think the best way is to use a hash to implement a set by using
the existant keys to represent the current members of the set.
...
Is this approach the simplest way?
Probably yes, but really it depends on what operations you
want to do on the set.
If you, for example, never want to check if certain elements
are included, you only want to iterate over the set,
then it's better to use an array (or a list).
This case is very common, just most people don't call that
a set, but a list.
C++ STL doesn't call that a set either.
Also, if the set consists of small integers,
and you don't want to iterate over them,
then it may be better to use an array like
my @set;
sub contains { @set{$_[0]}; }
sub add { @set{$_[0]} = 1; }
Update: parv is right, I don't know what I was
thinking when I wrote the above code.
The right code is
my @set;
sub contains { $set[$_[0]]; }
sub add { $set[$_[0]] = 1; }
Or you can use a bit vector like
my $set = "";
sub contains { vec($set, $_[0], 1); }
sub add { vec($set, $_[0], 1) = 1; }
Is there a better approach avoiding the assignment for the add?
Something like create $set{'foo'}?
Not really. Some people (me too sometimes) use
$set{"foo"}++;
but that's not really better at all, only shorter.
I think I don't need the hash entries to be defined. I just need
them to exist. (If you iterate over keys it will still return
entries that have existant but undefined values right?)
That's right.
If you do not insist on values to be defined, just exist,
the code you gave should still work.
Moreover, there's a little advantage in that approach:
you can add multiple elements to the set with a
shorter syntax:
$set{@elements} = ();
I however sometimes still represent a set in such a way
that all values are 1, because if I have
to test for inclusion in the set many times in the code,
I can just write $set{$elt} instead of
exists($set{$elt}) that way.
|