Thread overview | ||||||
---|---|---|---|---|---|---|
|
November 05, 2013 is there a merge for associative arrays | ||||
---|---|---|---|---|
| ||||
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; } |
November 05, 2013 Re: is there a merge for associative arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Davidson | 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
|
November 05, 2013 Re: is there a merge for associative arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Davidson | Also, please report the crash in Bugzilla if you haven't already. d.puremagic.com/issues/ |
November 09, 2013 Re: is there a merge for associative arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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, > bearophile I 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)); } } |
Copyright © 1999-2021 by the D Language Foundation