1 /**
2     Zips up ranges up together
3 */
4 module ddash.algorithm.zip;
5 
6 ///
7 unittest {
8     auto r1 = [[1, 2, 3], [4, 5, 6]];
9     assert(r1.zipEach.equal([[1, 4], [2, 5], [3, 6]]));
10     auto r2 = [[1, 3], [4, 5, 6]];
11     assert(r2.zipEach.equal([[1, 4], [3, 5]]));
12     auto r3 = [[1, 3], [], [4, 5, 6]];
13     assert(r3.zipEach.equal((int[][]).init));
14 }
15 
16 import ddash.common;
17 
18 /**
19     Zip a range of ranges together by element.
20 
21     I.e. the first elements of each range will be zipped up in to the first "element", the second elements
22     of each range will be zipped up to the second element, etc, where eaach element is also a range.
23 
24     The number of elemenets in each sub range of the returned range is equal to the input sub range
25     that has the lest number of elements.
26 
27     Params:
28         rangeOfRanges = a range of ranges.
29 
30     Returns:
31         A range of ranges
32 
33     Since:
34         0.0.1
35 */
36 auto zipEach(RoR)(RoR rangeOfRanges) if (from!"std.range".isInputRange!(from!"std.range".ElementType!RoR)) {
37     static struct Result {
38         import std.algorithm: map, any;
39         import std.range: drop;
40         RoR source;
41         size_t position = 0;
42         @property empty() const {
43             import std.range: empty;
44             return source.any!(a => a.drop(position).empty);
45         }
46         @property auto front() {
47             import std.range: front;
48             return source.map!(a => a.drop(position).front);
49         }
50         void popFront() {
51             position++;
52         }
53     }
54     return Result(rangeOfRanges);
55 }
56 
57 unittest {
58     auto r1 = [[1, 4], [2, 5], [3, 6]];
59     auto r2 = [[1, 2, 3], [4, 5, 6]].zipEach;
60     assert(equal(r1, r2));
61 }