A set type implemented as an AA wrapper
mark
mark at qtrac.eu
Thu Mar 12 08:51:24 UTC 2020
I use sets a lot and since I believe that D's rbtree is O(lg n)
for add/remove/in and that D's AA is O(1) for these, I want to
implement a set in terms of an AA.
Below is the code I've got so far. It allows for add and remove.
However, it has three problems (that I know of):
XXX: I need to use an if on the struct to restrict T to be a type
that supports toHash and opEquals (i.e., to be a valid AA key)
YYY: The range() method is clearly not good D style but I don't
know how to support foreach (item; aaset) ...
ZZZ: I can't figure out how to support the in operator.
// XXX how do I write the if to ensure T is a valid AA key that
suppors
// toHash & opEquals?
struct AAset(T) {
private {
alias Unit = void[0];
enum unit = Unit.init;
Unit[T] set;
}
size_t length() const { return set.length; }
void add(T item) { set[item] = unit; }
bool remove(T item) { return set.remove(item); }
// YYY is there a better way so that people can just use
// foreach (var; aaset)
auto range() { return set.byKey; }
bool opBinaryRight(string op)(T lhs) { // ZZZ doesn't work
static if (op == "in") return lhs in set;
else static assert(0, "operator " ~ op ~ " not
supported");
}
// TODO union(), intersection(), difference(),
symmetric_difference()
}
unittest {
import std.algorithm: sort;
import std.array: array;
import std.range: enumerate;
import std.stdio: writeln;
import std.typecons: Tuple;
alias Pair = Tuple!(int, "count", string, "word");
auto inputs = [Pair(1, "one"), Pair(2, "two"), Pair(3,
"three"),
Pair(4, "four"), Pair(4, "two"), Pair(5,
"five"),
Pair(6, "six")];
AAset!string words;
assert(words.length == 0);
foreach (pair; inputs) {
words.add(pair.word);
assert(words.length == pair.count);
}
auto len = words.length;
assert(!words.remove("missing"));
assert(words.remove("one"));
assert(words.length == len - 1);
auto expected = ["five", "four", "six", "three", "two"];
foreach (i, word; words.range.array.sort.enumerate)
assert(word == expected[i]);
/*
assert("Z" !in words);
assert("three" !in words);
*/
}
More information about the Digitalmars-d-learn
mailing list