digitalmars.D.learn - is there a merge for associative arrays
- Daniel Davidson (36/36) Nov 05 2013 The code below causes a crash. What is the idiomatic way to merge
- bearophile (7/33) Nov 05 2013 In D operators need to be defined inside structs/classes.
- Daniel Davidson (66/70) Nov 09 2013 I have something I would appreciate feedback/criticism on. My
- Meta (2/2) Nov 05 2013 Also, please report the crash in Bugzilla if you haven't already.
The code below causes a crash. What is the idiomatic way to merge associative arrays? If there is a simple version that allows the value at a key to be clobbered by the value of the right hand operand when there is a collision, that is a start. import std.stdio; void main() { double[string] a = [ "foo" : 22.2 ]; double[string] b = [ "bar" : 22.2 ]; writeln(a+b); } Is there a way to do something like this and have opApply be called for '+'? If so, is it a bad idea? import std.stdio; double[string] opApply(string op)(const double[string][] inputs ...) if(op == "+") { double[string] result; foreach( map ; inputs ) { foreach( key, value ; map ) { auto pval = key in result; if(pval) { *pval += value; } else { result[key] = value; } } } return result; } void main() { double[string] a = [ "foo" : 22.2 ]; double[string] b = [ "bar" : 22.2 ]; double[string] c = [ "bar" : 5 ]; auto d = a+b+c; }
Nov 05 2013
Daniel Davidson:Is there a way to do something like this and have opApply be called for '+'? If so, is it a bad idea? import std.stdio; double[string] opApply(string op)(const double[string][] inputs ...) if(op == "+") { double[string] result; foreach( map ; inputs ) { foreach( key, value ; map ) { auto pval = key in result; if(pval) { *pval += value; } else { result[key] = value; } } } return result; } void main() { double[string] a = [ "foo" : 22.2 ]; double[string] b = [ "bar" : 22.2 ]; double[string] c = [ "bar" : 5 ]; auto d = a+b+c; }In D operators need to be defined inside structs/classes. So write a function, it could have signature as: TV[TK] mergeAAs(TK, TV)(TV[TK] aas...) { It seems even fit for Phobos. Bye, bearophile
Nov 05 2013
On Tuesday, 5 November 2013 at 17:47:16 UTC, bearophile wrote:TV[TK] mergeAAs(TK, TV)(TV[TK] aas...) { It seems even fit for Phobos. Bye, bearophileI have something I would appreciate feedback/criticism on. My first stab at it worked, but had no support for passing in const/immutable. AA mergeAAs(alias fun = "a + b", AA)(AA[] aas...) if(isAssociativeArray!AA) { AA result; ... } Not sure if this is a good way or if there are better idiomatic ways, but here is what I have got. Any suggestions/improvements to make it more idiomatic would be appreciated. Is there already a DeepUnqual equivalent in phobos? Thanks Dan import std.stdio; import std.traits; import std.algorithm; import std.functional; template DeepUnqual(T) { static if(isAssociativeArray!T) { alias Unqual!(Unqual!(ValueType!T)[Unqual!(KeyType!T)]) DeepUnqual; } else static if(isDynamicArray!T) { alias Unqual!(Unqual!(ArrayElementType!T)[]) DeepUnqual; } else static if(isPointer!T) { alias Unqual!(PointerTarget!T) * DeepUnqual; } else { alias Unqual!T DeepUnqual; } } DeepUnqual!AA mergeAAs(alias fun = "a + b", AA)(AA[] aas...) if(isAssociativeArray!AA) { DeepUnqual!AA result; if(aas.length) { foreach( aa ; aas ) { foreach( k , v ; aa ) { auto found = k in result; if(found) { *found = binaryFun!fun(*found, v); } else { result[k] = v; } } } } return result; } void main() { alias double[string] AA; AA a = [ "foo":1.1, "bar":2.2 ]; AA b = [ "foo":1.1, "bard":2.2 ]; writeln(mergeAAs(a, b)); writeln(mergeAAs!q{a*b}(a, b)); { const AA ca = a.dup; const AA cb = b.dup; writeln(mergeAAs(ca,cb)); } { immutable AA ia = [ "foo":1.1, "bar":2.2 ]; immutable AA ib = [ "foo":1.1, "bard":2.2 ]; writeln(mergeAAs(ia,ib)); } }
Nov 09 2013
Also, please report the crash in Bugzilla if you haven't already. d.puremagic.com/issues/
Nov 05 2013