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,
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
Also, please report the crash in Bugzilla if you haven't already. d.puremagic.com/issues/
Nov 05 2013









"Daniel Davidson" <nospam spam.com> 