www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - is there a merge for associative arrays

reply "Daniel Davidson" <nospam spam.com> writes:
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
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
parent "Daniel Davidson" <nospam spam.com> writes:
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)); } }
Nov 09 2013
prev sibling parent "Meta" <jared771 gmail.com> writes:
Also, please report the crash in Bugzilla if you haven't already.

d.puremagic.com/issues/
Nov 05 2013