1 module anansi.container.set; 2 3 import std.algorithm, std.conv, std.range, std.stdio, std.traits; 4 5 /** 6 * 7 */ 8 struct Set (T) { 9 public this(Stuff)(Stuff stuff) 10 if (isInputRange!Stuff && 11 isImplicitlyConvertible!(ElementType!Stuff, T)) { 12 foreach(s; stuff) 13 insert(s); 14 } 15 16 public this(this) { 17 _payload = _payload.dup; 18 } 19 20 @property size_t length() const { 21 return _payload.length; 22 } 23 24 /** 25 * Inserts a new value into the set. 26 * Params: 27 * value = The value to insert into the set. 28 * 29 * Returns: 30 * Returns true if the value was inserted, or false if the value 31 * already existed in the set. 32 */ 33 public bool insert(T value) { 34 int n = _payload[value]++; 35 return (n == 0); 36 } 37 38 /** 39 * Inserts a range of elements into the set. 40 * 41 * Params: 42 * stuff = The range of items to insert into the set. 43 */ 44 public void insert(Stuff)(Stuff stuff) 45 if (isInputRange!Stuff && 46 isImplicitlyConvertible!(ElementType!Stuff, T)) { 47 foreach (s; stuff) 48 insert(s); 49 } 50 51 public bool contains(T value) const { 52 auto p = (value in _payload); 53 return (p !is null); 54 } 55 56 public int opApply(int delegate(ref T) dg) { 57 int rval = 0; 58 auto values = _payload.keys; 59 for(int i = 0; (i < values.length) && (rval != 0); ++i) 60 rval = dg(values[i]); 61 return rval; 62 } 63 64 private int[T] _payload; 65 } 66 67 unittest { 68 writeln("Set: Construction from a range."); 69 } 70 71 unittest { 72 writeln("Set: Unique values are added."); 73 Set!int s; 74 foreach(n; 0 .. 5) { 75 assert (s.insert(n), "Inserting a unique item should return true."); 76 } 77 78 assert (s.length == 5, "Expected length of 5, got: " ~to!string(s.length)); 79 foreach(n; 0 .. 5) { 80 assert (s.contains(n), "Expected value " ~ to!string(n) ~ " missing."); 81 } 82 } 83 84 unittest { 85 writeln("Set: Duplicate values are not added."); 86 Set!int s; 87 assert (s.insert(1), "Expected insert to return true."); 88 assert (!s.insert(1), "Expected duplicate insert to return false"); 89 assert (s.length == 1, "Expected length of 1, got " ~ to!string(s.length)); 90 }