A workmate has recently shown this piece of code to show how nice Python is (we are mostly C and growing C++ shop):

    import json
    from itertools import chain

srv1 = {'acs': {'ver': '1.2.3', 'rev': '6f2260d'}, 'cms': {'ver': '4.5', 'rev': 'b17a67e'}, 'ots': {'ver': '6.7.80', 'rev': '4f487d2'}} srv2 = {'acs': {'ver': '1.2.3', 'rev': '6f2260d'}, 'cms': {'ver': '5.1', 'rev': '2a56c53'}, 'vaa': {'ver': '0.7', 'rev': '00852cb'}}


    def aget(d, k1, k2):
        return d.get(k1, {}).get(k2, '')

    aa = ['ver', 'rev']
    kk = set(chain(srv1.keys(), srv2.keys()))
dd = [dict(_name=k, **{a + str(i): aget(d, k, a) for a in aa for i, d in enumerate([srv1, srv2])}) for k in sorted(kk)]

    print(json.dumps(dd, indent=2, sort_keys=True))


Output is:

    [
      {
        "_name": "acs",
        "rev0": "6f2260d",
        "rev1": "6f2260d",
        "ver0": "1.2.3",
        "ver1": "1.2.3"
      },
      {
        "_name": "cms",
        "rev0": "b17a67e",
        "rev1": "2a56c53",
        "ver0": "4.5",
        "ver1": "5.1"
      },
      {
        "_name": "ots",
        "rev0": "4f487d2",
        "rev1": "",
        "ver0": "6.7.80",
        "ver1": ""
      },
      {
        "_name": "vaa",
        "rev0": "",
        "rev1": "00852cb",
        "ver0": "",
        "ver1": "0.7"
    ]
      }

Another coworker replied with Scala equivalent. So I thought, why wouldn't I join the party and translate that to D :)

My best take so far is (with some D-intro comments https://run.dlang.io/is/GxsauU):

    import std.stdio;
    import std.algorithm;
    import std.range;
    import std.array;
    import std.conv;
    import std.json;

    void main()
    {
        // not `immutable` to describe one less thing
        const srv1 = [
            "acs": ["ver": "1.2.3", "rev": "6f2260d"],
            "cms": ["ver": "4.5", "rev": "b17a67e"],
            "ots": ["ver": "6.7.80", "rev": "4f487d2"]];
        const srv2 = [
            "acs": ["ver": "1.2.3", "rev": "6f2260d"],
            "cms": ["ver": "5.1", "rev": "2a56c53"],
            "vaa": ["ver":    "0.7", "rev": "00852cb"]];

        string[string][] result;
        chain(srv1.keys, srv2.keys)
            .sort                                       
            .uniq                                       
            .each!( (uniqComp) {        
                auto verInfo = ["_name": uniqComp];
                [srv1, srv2]
                    .enumerate
                    .each!( serv =>
                            ["ver", "rev"].each!( prop =>
verInfo[prop ~ serv.index.to!string] = serv.value.get(uniqComp, ["": ""]).get(prop, ""))
                    );
/+ // The same as above and I like this better, actually
                foreach(servIdx, serv; [srv1, srv2].enumerate){
                    foreach(prop; ["ver", "rev"])
                        verInfo[prop ~ servIdx.to!string]
= serv.get(uniqComp, ["": ""]).get(prop, "");
                } +/

                result ~= verInfo;
            });
        writeln("---");
        writeln(JSONValue(result).toPrettyString());
        writeln("---");
    }

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.

Suggestion are welcome!

---
Alexander

Reply via email to