Jump to page: 1 2
Thread overview
How to imporve D-translation of these Python list comprehensions ?
Jan 15, 2018
xenon325
Jan 15, 2018
Igor Shirkalin
Feb 01, 2018
Russel Winder
Jan 15, 2018
lobo
Feb 01, 2018
Russel Winder
Feb 01, 2018
bauss
Jan 15, 2018
Biotronic
Jan 15, 2018
Timon Gehr
Jan 15, 2018
Timon Gehr
January 15, 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
January 15, 2018
On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
> A workmate has recently shown this piece of code to show how nice Python is (we are mostly C and growing C++ shop):
>     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)]

This is the most terrible Python code I have ever seen.
If you know Python, could you please unroll to more readable form?

> Suggestion are welcome!

>
> ---
> Alexander


January 15, 2018
On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
> A workmate has recently shown this piece of code to show how nice Python is (we are mostly C and growing C++ shop):
>
> [...]

Well if that is what they can do in Python I'd hate to see their C++! They have done a great job making Python code read like Perl. This looks like something you'd see in an assignment at uni; "Decipher this Python code and port to your language of choice" :)
January 15, 2018
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
January 15, 2018
On 15.01.2018 20:05, 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.
> 
> Suggestion are welcome!

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

auto aa(R)(R r){
    typeof(r.front[1])[typeof(r.front[0])] a;
    foreach(x;r) a[x[0]] = x[1];
    return a;
}
alias emap(alias a) = map!(x => a(x.expand));

void main(){
    auto srv1 = [
        "acs": ["ver": "1.2.3", "rev": "6f2260d"],
        "cms": ["ver": "4.5", "rev": "b17a67e"],
        "ots": ["ver": "6.7.80", "rev": "4f487d2"]];
    auto srv2 = [
        "acs": ["ver": "1.2.3", "rev": "6f2260d"],
        "cms": ["ver": "5.1", "rev": "2a56c53"],
        "vaa": ["ver":    "0.7", "rev": "00852cb"]];

    chain(srv1.keys, srv2.keys).sort.uniq
        .map!(k => chain(only(tuple("_name", k)),
                         cartesianProduct(only("ver", "rev"), only(srv1, srv2).enumerate)
                         .emap!((prop, srv) => tuple(text(prop, srv.index), srv.value.get(k, null).get(prop, "")))
              ).aa).array.JSONValue.toPrettyString.writeln;
}

January 15, 2018
On 15.01.2018 22:51, Timon Gehr wrote:
> auto aa(R)(R r){
>      typeof(r.front[1])[typeof(r.front[0])] a;
>      foreach(x;r) a[x[0]] = x[1];
>      return a;
> }

Actually, better to use std.array.assocArray.

import std.stdio, std.algorithm, std.range, std.array, std.conv, std.json, std.typecons;
alias emap(alias a) = map!(x => a(x.expand));

void main(){
    auto srv1 = [
        "acs": ["ver": "1.2.3", "rev": "6f2260d"],
        "cms": ["ver": "4.5", "rev": "b17a67e"],
        "ots": ["ver": "6.7.80", "rev": "4f487d2"]];
    auto srv2 = [
        "acs": ["ver": "1.2.3", "rev": "6f2260d"],
        "cms": ["ver": "5.1", "rev": "2a56c53"],
        "vaa": ["ver": "0.7", "rev": "00852cb"]];

    chain(srv1.keys, srv2.keys).sort.uniq
        .map!(k => chain(only(tuple("_name", k)),
                         cartesianProduct(only("ver", "rev"), only(srv1, srv2).enumerate)
                         .emap!((prop, srv) => tuple(text(prop, srv.index), srv.value.get(k, null).get(prop, "")))
              ).assocArray).array.JSONValue.toPrettyString.writeln;
}
February 01, 2018
On Mon, 2018-01-15 at 20:27 +0000, Igor Shirkalin via Digitalmars-d- learn wrote:
> On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
> > A workmate has recently shown this piece of code to show how
> > nice Python is (we are mostly C and growing C++ shop):
> >     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)]
> 
> This is the most terrible Python code I have ever seen.
> If you know Python, could you please unroll to more readable form?

Actually I have seen worse, but… I think the way this Python code is presented is fairly dreadful.

I am fiddling with trying to provide a better version. If people are interested in this I can share in a while when it's ready.

-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


February 01, 2018
On Mon, 2018-01-15 at 21:13 +0000, lobo via Digitalmars-d-learn wrote:
> On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
> > A workmate has recently shown this piece of code to show how nice Python is (we are mostly C and growing C++ shop):
> > 
> > [...]
> 
> Well if that is what they can do in Python I'd hate to see their C++! They have done a great job making Python code read like Perl. This looks like something you'd see in an assignment at uni; "Decipher this Python code and port to your language of choice" :)

Apart from the slur on Perl, I have to agree with this. Using a dreadful bit of Python code is the start of a downward spiral of expectation and programming in other languages.

As noted earlier, I am working on a nicer rendering of this algorithm, and will be happy to share if people are interested.

-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


February 01, 2018
On Thursday, 1 February 2018 at 11:59:23 UTC, Russel Winder wrote:
> On Mon, 2018-01-15 at 21:13 +0000, lobo via Digitalmars-d-learn wrote:
>> On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
>> > A workmate has recently shown this piece of code to show how nice Python is (we are mostly C and growing C++ shop):
>> > 
>> > [...]
>> 
>> Well if that is what they can do in Python I'd hate to see their C++! They have done a great job making Python code read like Perl. This looks like something you'd see in an assignment at uni; "Decipher this Python code and port to your language of choice" :)
>
> Apart from the slur on Perl, I have to agree with this. Using a dreadful bit of Python code is the start of a downward spiral of expectation and programming in other languages.
>
> As noted earlier, I am working on a nicer rendering of this algorithm, and will be happy to share if people are interested.

I'd be interested in seeing the result.
February 01, 2018
On Monday, 15 January 2018 at 19:05:52 UTC, xenon325 wrote:
>     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)]

But that was really verbose, why didn't he contract everything into one line?

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

:*)

« First   ‹ Prev
1 2