Combining "chunkBy" and "until" algorithms

Timon Gehr via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Nov 5 06:57:23 PDT 2016


On 04.11.2016 09:04, Jacob Carlborg wrote:
> I have a file with a bunch of lines I want to process. I want to process
> these lines line by line. Most of these lines have the same pattern.
> Some of the lines have a different pattern. I want to bundle those
> lines, which have a non-standard pattern, together with the last line
> that had the standard pattern. The number of lines with a non-standard
> pattern is unknown. Are there some algorithms in Phobos that can help
> with this?
>
> Maybe an algorithm combining "chunkBy" and "until" could do it?
>
> Currently I'm using a standard for loop iterating over the lines. I'm
> always looking at the current line and the next line. When the current
> line is the standard pattern and the next line is is not, I do a
> separate loop until I see a standard pattern again, collecting the lines
> with the non-standard pattern in an array.
>

"chunkBy" a predicate that checks whether a line is standard. Use 'zip' 
to focus two adjacent chunks at the same time. Use 'filter' to only 
consider adjacent chunks where the first chunk consists of standard 
lines. Then extract the last line of the first chunk and combine it with 
the second chunk.

import std.algorithm, std.range, std.typecons;
import std.stdio;

void main(){
     auto data=["standard1","standard2","non-standard1","standard3",
                "non-standard2","non-standard3","standard4"];
     static bool isStandard(string s){
         return s.startsWith("standard");
     }
     auto chunks=data.chunkBy!isStandard;
     auto pairs=zip(chunks.save,chunks.dropOne);
     auto result=pairs.filter!(x=>x[0][0])
         .map!(x=>tuple(last(x[0][1]),x[1][1]));
     result.each!(x=>writeln(x[0],", (",x[1].joiner(", "),")"));
}

auto last(R)(R r){ // missing from Phobos AFAIK
     return zip(r.save,r.dropOne.recurrence!"a[n-1].dropOne"
                .until!(x=>x.empty))
         .filter!(x=>x[1].empty).front[0];
}

Prints:
standard2, (non-standard1)
standard3, (non-standard2, non-standard3)



More information about the Digitalmars-d-learn mailing list