How to imporve D-translation of these Python list comprehensions ?
xenon325
anm at programmer.net
Mon Jan 15 19:05:52 UTC 2018
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
More information about the Digitalmars-d-learn
mailing list