RehashingAA

A wrapper around a native associative array that you can controllably set to automatically rehash as entries are added.

Constructors

this
this(AA aa)

Constructor.

Members

Functions

aaOf
auto ref aaOf()

Returns the internal associative array, for when the wrapper is insufficient.

byKey
auto byKey()

Wraps the internal associative array's byKey function.

byKeyValue
auto byKeyValue()

Wraps the internal associative array's byKeyValue function.

byValue
auto byValue()

Wraps the internal associative array's byValue function.

clear
void clear()

Clears the internal associative array and all counters.

dup
auto dup(bool copyState)

Duplicates this. Explicitly copies the internal associative array.

get
auto ref get(K key, V value)

Retrieves the value for the key key, or returns the default value if there was none.

keys
auto keys()

Wraps the internal associative array's keys function.

length
auto length()

Returns the length of the internal associative array.

maybeRehash
auto maybeRehash()

Bumps the internal counter of new keys since the last rehash, and depending on the resulting value of it, maybe rehashes.

newKeysSinceLastRehash
auto newKeysSinceLastRehash()

The number of new entries that has been added since the last rehash. Accessor.

numRehashes
auto numRehashes()

The number of times this instance has rehashed itself. Accessor.

opAssign
void opAssign(V[K] aa)

Inherit a native associative array into aa.

opBinaryRight
auto opBinaryRight(K key)

Wraps key in aa to the internal associative array.

opCast
auto ref opCast()

Allows for casting this into the base associative array type.

opEquals
auto opEquals(typeof(this) other)

Implements opEquals for this type, comparing the internal associative array with that of another RehashingAA.

opEquals
auto opEquals(AA other)

Implements opEquals for this type, comparing the internal associative array with a different one.

opIndex
auto ref opIndex(K key)

Returns the value for the passed key in the internal associative array.

opIndexAssign
void opIndexAssign(V value, K key)

Assigns a value into the internal associative array. If it created a new entry, then call maybeRehash to bump the internal counter and maybe rehash.

opIndexOpAssign
void opIndexOpAssign(U value, K key)

Performs an assingment operation on a value in the internal associative array.

opIndexUnary
auto ref opIndexUnary(K key)

Performs a unary operation on a value in the internal associative array.

rehash
auto ref rehash()

Rehashes the internal associative array, bumping the rehash counter and zeroing the keys-added counter. Additionally invokes the onRehashDg delegate.

remove
auto remove(K key)

Removes a key from the aa associative array by merely invoking .remove.

require
auto ref require(K key, V value)

Returns the value for the key key, inserting value lazily if it is not present.

uniqueKey
auto uniqueKey(K min, K max, V value)

Reserves a unique key in the associative array.

update
void update(K key, V delegate() createDg, U delegate(K) updateDg)

Updates the value for the key key in the internal associative array, invoking the first of the passed delegate to insert a new value if it doesn't exist, or the second selegate to modify it in place if it does.

values
auto values()

Wraps the internal associative array's values function.

Variables

_lengthAtLastRehash
size_t _lengthAtLastRehash;

The number of keys (and length of the array) when the last rehash took place. Private value.

_newKeysSinceLastRehash
uint _newKeysSinceLastRehash;

The number of new entries that has been added since the last rehash. Private value.

_numRehashes
uint _numRehashes;

The number of times this instance has rehashed itself. Private value.

aa
AA aa;

Internal associative array.

minimumNeededForRehash
uint minimumNeededForRehash;

The minimum number of additions needed before the first rehash takes place.

onRehashDg
void delegate(ref AA) @(system) onRehashDg;

Delegate called when rehashing takes place.

rehashThresholdMultiplier
double rehashThresholdMultiplier;

The modifier by how much more entries must be added before another rehash takes place, with regards to the current aa length.

Parameters

AA

Associative array type.

V

Value type.

K

Key type.

Examples

1 import std.conv : to;
2 
3 {
4     uint counter;
5 
6     void dg(ref int[string] aa)
7     {
8         ++counter;
9     }
10 
11     RehashingAA!(int[string]) aa;
12     aa.onRehashDg = &dg;
13     aa.minimumNeededForRehash = 2;
14 
15     aa["abc"] = 123;
16     aa["def"] = 456;
17     assert((aa.newKeysSinceLastRehash == 2), aa.newKeysSinceLastRehash.to!string);
18     assert((aa.numRehashes == 0), aa.numRehashes.to!string);
19     aa["ghi"] = 789;
20     assert((aa.numRehashes == 1), aa.numRehashes.to!string);
21     assert((aa.newKeysSinceLastRehash == 0), aa.newKeysSinceLastRehash.to!string);
22     aa.rehash();
23     assert((aa.numRehashes == 2), aa.numRehashes.to!string);
24     assert((counter == 2), counter.to!string);
25 
26     auto realAA = cast(int[string])aa;
27     assert("abc" in realAA);
28     assert("def" in realAA);
29 
30     auto alsoRealAA = aa.aaOf;
31     assert("ghi" in alsoRealAA);
32     assert("jkl" !in alsoRealAA);
33 
34     auto aa2 = aa.dup(copyState: true);
35     assert((aa2.numRehashes == 2), aa2.numRehashes.to!string);
36     aa2["jkl"] = 123;
37     assert("jkl" in aa2);
38     assert("jkl" !in aa);
39 
40     auto aa3 = aa.dup();  //(copyState: false);
41     assert(!aa3.numRehashes, aa3.numRehashes.to!string);
42     assert(aa3.aaOf == aa.aaOf);
43     assert(aa3.aaOf !is aa.aaOf);
44 }
45 {
46     RehashingAA!(int[int]) aa;
47     aa[1] = 2;
48     ++aa[1];
49     assert((aa[1] == 3), aa[1].to!string);
50     assert((-aa[1] == -3), (-aa[1]).to!string);
51 }
52 {
53     RehashingAA!(int[int]) aa;
54     aa[1] = 42;
55     aa[1] += 1;
56     assert(aa[1] == 43);
57 
58     aa[1] *= 2;
59     assert(aa[1] == 86);
60 }
61 {
62     RehashingAA!(int[string]) aa;
63     static assert(is(typeof(aa.aaOf()) == int[string]));
64 
65     aa["abc"] = 123;
66     auto native = cast(int[string])aa;
67     assert(native["abc"] == 123);
68 }
69 {
70     RehashingAA!(int[string]) aa;
71     aa["abc"] = 123;
72     aa["def"] = 456;
73     assert((aa.length == 2), aa.length.to!string);
74     aa.remove("abc");
75     assert((aa.length == 1), aa.length.to!string);
76     aa.remove("def");
77     assert(!aa.length, aa.length.to!string);
78 }
79 {
80     RehashingAA!(int[string]) aa;
81     aa["abc"] = 123;
82     aa["def"] = 456;
83     aa["ghi"] = 789;
84 
85     foreach (value; aa.byValue)
86     {
87         import std.algorithm.comparison : among;
88         assert(value.among!(123, 456, 789), value.to!string);
89     }
90 }
91 {
92     RehashingAA!(int[string]) aa;
93     aa["abc"] = 123;
94     aa["def"] = 456;
95     aa["ghi"] = 789;
96 
97     foreach (key; aa.byKey)
98     {
99         assert(key in aa);
100     }
101 }
102 {
103     RehashingAA!(int[string]) aa;
104     aa["abc"] = 123;
105     aa["def"] = 456;
106     aa["ghi"] = 789;
107 
108     auto values = aa.values;  // allocate it once
109 
110     // Order cannot be relied upon
111     foreach (val; [ 123, 456, 789 ])
112     {
113         import std.algorithm.searching : canFind;
114         assert(values.canFind(val));
115     }
116 }
117 {
118     RehashingAA!(int[string]) aa;
119     aa["abc"] = 123;
120     aa["def"] = 456;
121     aa["ghi"] = 789;
122 
123     auto keys = aa.keys;  // allocate it once
124 
125     // Order cannot be relied upon
126     foreach (key; [ "abc", "def", "ghi" ])
127     {
128         assert(key in aa);
129     }
130 }
131 {
132     RehashingAA!(int[string]) aa;
133     aa["abc"] = 123;
134     aa["def"] = 456;
135     aa["ghi"] = 789;
136 
137     foreach (kv; aa.byKeyValue)
138     {
139         assert(kv.key in aa);
140         assert(aa[kv.key] == kv.value);
141     }
142 }
143 {
144     RehashingAA!(string[int]) aa;
145     string hello = aa.require(42, "hello");
146     assert(hello == "hello");
147     assert(aa[42] == "hello");
148 }
149 {
150     RehashingAA!(int[int]) aa;
151     aa[1] = 42;
152     aa[2] = 99;
153 
154     assert(aa.get(1, 0) == 42);
155     assert(aa.get(2, 0) == 99);
156     assert(aa.get(0, 0) == 0);
157     assert(aa.get(3, 999) == 999);
158 
159     assert(0 !in aa);
160     assert(3 !in aa);
161 }
162 {
163     RehashingAA!(int[int]) aa;
164 
165     assert(1 !in aa);
166 
167     aa.update(1,
168         () => 42,
169         (int i) => i + 1);
170     assert(aa[1] == 42);
171 
172     aa.update(1,
173         () => 42,
174         (int i) => i + 1);
175     assert(aa[1] == 43);
176 }
177 {
178     RehashingAA!(string[int]) aa1;
179     aa1[1] = "one";
180 
181     RehashingAA!(string[int]) aa2;
182     aa2[1] = "one";
183     assert(aa1 == aa2);
184 
185     aa2[2] = "two";
186     assert(aa1 != aa2);
187 
188     aa1[2] = "two";
189     assert(aa1 == aa2);
190 }
191 {
192     RehashingAA!(string[int]) aa1;
193     aa1[1] = "one";
194     aa1[2] = "two";
195 
196     string[int] aa2;
197     aa2[1] = "one";
198 
199     assert(aa1 != aa2);
200 
201     aa2[2] = "two";
202     assert(aa1 == aa2);
203 }
204 {
205     RehashingAA!(string[int]) aa;
206     int i = aa.uniqueKey;
207     assert(i > 0);
208     assert(i in aa);
209     assert(aa[i] == string.init);
210 }