On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
I think, most clear code would be with tripple `foreach`, so I'll go with that. But probably someone will come up with something better and range-ier.

I will admit clarity has suffered, but I like the brevity:

import std.json : JSONValue;
import std.array : array, assocArray;
import std.range : enumerate, byPair;
import std.algorithm : sort, joiner, map, uniq, each;
import std.typecons : tuple;
import std.conv : to;
import std.stdio : writeln;

unittest {
immutable srv1 = ["acs": ["ver": "1.2.3", "rev": "6f2260d"], "cms": ["ver": "4.5", "rev": "b17a67e"], "ots": ["ver": "6.7.80", "rev": "4f487d2"]]; immutable srv2 = ["acs": ["ver": "1.2.3", "rev": "6f2260d"], "cms": ["ver": "5.1", "rev": "2a56c53"], "vaa": ["ver": "0.7", "rev": "00852cb"]];
    immutable keys = ["rev", "ver"];
    immutable srvs = [srv1, srv2];

alias aget = (name, key) => srvs.map!(s => s.get(name, [key:""])[key]); alias bget = (name, key) => aget(name, key).enumerate.map!(b => tuple(key~b.index.to!string, b.value)); alias merge = (aa1, aa2) => (aa2.byPair.each!(kv => aa1[kv.key] = kv.value), aa1);

    auto result = srvs
        .map!(s => s.byKey)
        .joiner
        .array
        .sort
        .uniq
.map!(name => merge(keys.map!(key => bget(name, key)).joiner.assocArray, ["_name": name]))
        .array;

    writeln(JSONValue(result).toPrettyString());
}

--
  Simen

Reply via email to