Skip to content

Commit a483d6a

Browse files
committed
extend string-map API
1 parent bd61c40 commit a483d6a

3 files changed

Lines changed: 105 additions & 7 deletions

File tree

source/mir/algebraic_alias/ion.d

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ alias IonAlgebraic = Algebraic!Ion_;
6464
version(mir_test)
6565
unittest
6666
{
67+
import mir.test: should;
6768
import mir.ndslice.topology: map;
6869
import mir.array.allocation: array;
6970

@@ -158,6 +159,14 @@ unittest
158159
assert(fromAA.object["a"] == 3);
159160
assert(fromAA.object["b"] == "b");
160161

162+
// object foreach iteration
163+
long sum;
164+
foreach (ref key, ref val; fromAA.object)
165+
if (key == "a")
166+
sum += val.get!long;
167+
sum.should == 3;
168+
169+
// annotations
161170
auto annotated = Annotated!IonAlgebraic(["birthday"], Timestamp("2001-01-01"));
162171
value = annotated;
163172
assert(value == annotated);

source/mir/algebraic_alias/json.d

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ version(mir_test)
4949
@safe pure
5050
unittest
5151
{
52+
import mir.test: should;
5253
import mir.ndslice.topology: map;
5354
import mir.array.allocation: array;
5455

@@ -141,4 +142,11 @@ unittest
141142
JsonAlgebraic fromAA = ["a" : JsonAlgebraic(3), "b" : JsonAlgebraic("b")];
142143
assert(fromAA.object["a"] == 3);
143144
assert(fromAA.object["b"] == "b");
145+
146+
// object foreach iteration
147+
long sum;
148+
foreach (ref key, ref val; fromAA.object)
149+
if (key == "a")
150+
sum += val.get!long;
151+
sum.should == 3;
144152
}

source/mir/string_map.d

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,14 @@ struct StringMap(T)
258258
return implementation ? implementation.length : 0;
259259
}
260260

261+
/++
262+
Returns: number of elements in the table.
263+
+/
264+
bool empty()() @safe pure nothrow @nogc const @property
265+
{
266+
return !implementation || implementation.length == 0;
267+
}
268+
261269
version(mir_test) static if (is(T == int))
262270
///
263271
@safe pure unittest
@@ -345,8 +353,8 @@ struct StringMap(T)
345353
*/
346354
auto byKeyValue(this This)() @trusted pure nothrow @nogc
347355
{
348-
import mir.ndslice.topology: zip, map;
349-
return keys.zip(values).map!KeyValue;
356+
import mir.ndslice.topology: map;
357+
return this.opIndex.map!KeyValue;
350358
}
351359

352360
version(mir_test) static if (is(T == int))
@@ -369,6 +377,19 @@ struct StringMap(T)
369377
assert(map.values == [4.0]);
370378
}
371379

380+
///
381+
auto opIndex(this This)() @trusted pure nothrow @nogc
382+
{
383+
import mir.ndslice.topology: zip;
384+
return keys.zip(values);
385+
}
386+
387+
///
388+
auto dup(this This)() @trusted
389+
{
390+
return StringMap(keys.dup, values.dup);
391+
}
392+
372393
/++
373394
(Property) Gets the current capacity of an associative array.
374395
The capacity is the size that the underlaynig slices can grow to before the underlying arrays may be reallocated or extended.
@@ -688,7 +709,7 @@ struct StringMap(T)
688709
689710
Complexity: `O(log(s))`, where `s` is the number of the keys with the same length as the input key.
690711
+/
691-
inout(T) get()(scope const(char)[] key, lazy inout(T) defaultValue)
712+
inout(T) get()(scope const(char)[] key, lazy inout(T) defaultValue) inout
692713
{
693714
size_t index;
694715
if (implementation && implementation.findIndex(key, index))
@@ -808,6 +829,7 @@ struct StringMap(T)
808829
}
809830

810831
///
832+
version(mir_test) static if (is(T == int))
811833
@safe pure nothrow unittest
812834
{
813835
StringMap!int map = ["k": 1];
@@ -971,22 +993,22 @@ struct StringMap(T)
971993
return _length;
972994
}
973995

974-
inout(string)[] keys()() @trusted inout @property
996+
inout(string)[] keys()() @trusted inout @property pure @nogc nothrow
975997
{
976998
return _keys[0 .. _length];
977999
}
9781000

979-
inout(T)[] values()() @trusted inout @property
1001+
inout(T)[] values()() @trusted inout @property pure @nogc nothrow
9801002
{
9811003
return _values[0 .. _length];
9821004
}
9831005

984-
inout(U)[] indices()() @trusted inout @property
1006+
inout(U)[] indices()() @trusted inout @property pure @nogc nothrow
9851007
{
9861008
return _indices[0 .. _length];
9871009
}
9881010

989-
inout(U)[] lengthTable()() @trusted inout @property
1011+
inout(U)[] lengthTable()() @trusted inout @property pure @nogc nothrow
9901012
{
9911013
return _lengthTable;
9921014
}
@@ -1217,3 +1239,62 @@ version(mir_test)
12171239

12181240
assert((*tkType) == "Bearer"); // *tkType contains value 3599
12191241
}
1242+
1243+
///
1244+
template intersectionMap(alias merger)
1245+
{
1246+
///
1247+
StringMap!V intersectionMap(V)(StringMap!V a, StringMap!V b)
1248+
{
1249+
import mir.functional : naryFun;
1250+
typeof(return) res;
1251+
foreach (key, ref value; a)
1252+
if (auto bValPtr = key in b)
1253+
res[key] = naryFun!merger(value, *bValPtr);
1254+
return res;
1255+
}
1256+
}
1257+
1258+
///
1259+
version(mir_test)
1260+
@safe pure
1261+
unittest {
1262+
import mir.test: should;
1263+
import mir.string_map : StringMap;
1264+
auto m0 = StringMap!int(["foo", "bar"], [1, 2]);
1265+
auto m1 = StringMap!int(["foo"], [2]);
1266+
auto m2 = StringMap!int(["foo"], [3]);
1267+
intersectionMap!"a + b"(m0, m1).should == m2;
1268+
}
1269+
1270+
///
1271+
template unionMap(alias merger)
1272+
{
1273+
///
1274+
StringMap!V unionMap(V)(StringMap!V a, StringMap!V b)
1275+
{
1276+
import mir.functional : naryFun;
1277+
typeof(return) res;
1278+
foreach (key, ref value; a)
1279+
if (auto bValPtr = key in b)
1280+
res[key] = naryFun!merger(value, *bValPtr);
1281+
else
1282+
res[key] = value;
1283+
foreach (key, ref value; b)
1284+
if (key !in res)
1285+
res[key] = value;
1286+
return res;
1287+
}
1288+
}
1289+
1290+
///
1291+
version(mir_test)
1292+
@safe pure
1293+
unittest {
1294+
import mir.test: should;
1295+
import mir.string_map : StringMap;
1296+
auto m0 = StringMap!int(["foo", "bar"], [1, 2]);
1297+
auto m1 = StringMap!int(["foo"], [2]);
1298+
auto m2 = StringMap!int(["foo", "bar"], [3, 2]);
1299+
unionMap!"a + b"(m0, m1).should == m2;
1300+
}

0 commit comments

Comments
 (0)