@@ -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