[Issue 5968] New: Two changes for std.algorithm.group()?

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon May 9 03:18:51 PDT 2011


http://d.puremagic.com/issues/show_bug.cgi?id=5968

           Summary: Two changes for std.algorithm.group()?
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody at puremagic.com
        ReportedBy: bearophile_hugs at eml.cc


--- Comment #0 from bearophile_hugs at eml.cc 2011-05-09 03:14:50 PDT ---
Andrej Mitrovic has asked to split the following array in three arrays/ranges,
according to the splitting predicate x<32:

[64, 64, 64, 32, 31, 16, 32, 33, 64]


A solution using group():


import std.stdio, std.algorithm;

void main() {
    auto arr = [64, 64, 64, 32, 31, 16, 32, 33, 64];

    int last = 0;
    foreach (g; group!q{ (a < 32) == (b < 32) }(arr)) {
        writeln(arr[last .. last+g[1]]);
        last += g[1];
    }
}


Output:
[64, 64, 64, 32]
[31, 16]
[32, 33, 64]


Andrei has suggested the second item of the tuples that group() yields to be a
lazy range instead just of counter (untested code). This is an improvement, and
it makes group() closer to the Python itertools.groupby(). With this change the
code becomes simpler:


import std.stdio, std.algorithm;

void main() {
    auto arr = [64, 64, 64, 32, 31, 16, 32, 33, 64];

    foreach (g; group!q{ (a < 32) == (b < 32) }(arr))
        writeln(g[1]); // g[1] is lazy  
}


In Python groupby uses a key mapping function, like D schwartzSort(), that's
more handy:

>>> from itertools import groupby
>>> arr = [64, 64, 64, 32, 31, 16, 32, 33, 64]
>>> [list(g) for h,g in groupby(arr, key = lambda x: x < 32)]
[[64, 64, 64, 32], [31, 16], [32, 33, 64]]


I suggest to change D group() to follow the Python groupby() design on this
too. With this the D code improves further (untested):

import std.stdio, std.algorithm;

void main() {
    auto arr = [64, 64, 64, 32, 31, 16, 32, 33, 64];

    foreach (g; group!q{ a < 32 }(arr))
        writeln(g[1]);
}


Implementation note: unlike schwartzSort() there isn't a need to memorize the
results of all the key mapping functions, this avoids slow memory allocations.


With tuple unpacking syntax sugar:


import std.stdio, std.algorithm;

void main() {
    auto arr = [64, 64, 64, 32, 31, 16, 32, 33, 64];

    foreach ((h, g); group!q{ a < 32 }(arr))
        writeln(g);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list