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 static if (__VERSION__ >= 2088L)
163 {{
164     RehashingAA!(int[int]) aa;
165 
166     assert(1 !in aa);
167 
168     aa.update(1,
169         () => 42,
170         (int i) => i + 1);
171     assert(aa[1] == 42);
172 
173     aa.update(1,
174         () => 42,
175         (int i) => i + 1);
176     assert(aa[1] == 43);
177 }}
178 {
179     RehashingAA!(string[int]) aa1;
180     aa1[1] = "one";
181 
182     RehashingAA!(string[int]) aa2;
183     aa2[1] = "one";
184     assert(aa1 == aa2);
185 
186     aa2[2] = "two";
187     assert(aa1 != aa2);
188 
189     aa1[2] = "two";
190     assert(aa1 == aa2);
191 }
192 {
193     RehashingAA!(string[int]) aa1;
194     aa1[1] = "one";
195     aa1[2] = "two";
196 
197     string[int] aa2;
198     aa2[1] = "one";
199 
200     assert(aa1 != aa2);
201 
202     aa2[2] = "two";
203     assert(aa1 == aa2);
204 }
205 {
206     RehashingAA!(string[int]) aa;
207     int i = aa.uniqueKey;
208     assert(i > 0);
209     assert(i in aa);
210     assert(aa[i] == string.init);
211 }