1 /**
2     Flattens a range one level deep by removing non truthy values.
3 */
4 module ddash.algorithm.flatten;
5 
6 ///
7 unittest {
8     auto arrayOfArrays = [[[1]], [[]], [[2], [3]], [[4]]];
9 
10     // remove emptys
11     assert(arrayOfArrays.flatten.equal([[1], [], [2], [3], [4]]));
12     assert([[1], [], [2, 3], [4]].flatten.equal([1, 2, 3, 4]));
13 
14     // remove empty all the way down
15     assert(arrayOfArrays.flattenDeep.equal([1, 2, 3, 4]));
16 
17     import optional;
18     assert([some(some(3)), no!(Optional!int), some(some(2))].flattenDeep.equal([3, 2]));
19 }
20 
21 import ddash.common;
22 
23 /**
24     Flattens a range one level deep by removing anything that's empty
25 
26     Params:
27         range = an input range
28 
29     Returns:
30         A flattened range
31 
32     Since:
33         0.0.1
34 */
35 auto flatten(Range)(Range range) if (from!"std.range".isInputRange!Range) {
36     import std.range: ElementType, isInputRange;
37     static if (isInputRange!(ElementType!Range))
38     {
39         import std.algorithm: joiner;
40         return range.joiner;
41     }
42     else
43     {
44         return range;
45     }
46 }
47 
48 unittest {
49     assert([[[1]], [[]], [[2], [3]], [[4]]].flatten.equal([[1], [], [2], [3], [4]]));
50     assert([[1], [], [2, 3], [4]].flatten.equal([1, 2, 3, 4]));
51 }
52 
53 unittest {
54     import optional;
55     assert([some(3), no!int, some(2)].flatten.equal([3, 2]));
56     assert([some(some(3)), no!(Optional!int), some(some(2))].flatten.equal([some(3), some(2)]));
57 }
58 
59 /**
60     Flattens a range all the way down
61 
62     Params:
63         range = an input range
64 
65     Returns:
66         A flattened range
67 
68     Since:
69         0.0.1
70 */
71 auto flattenDeep(Range)(Range range) if (from!"std.range".isInputRange!Range) {
72     import std.range: ElementType, isInputRange;
73     import ddash.algorithm: flatten;
74     static if (isInputRange!(ElementType!Range))
75     {
76         return range
77             .flatten
78             .flattenDeep;
79     }
80     else
81     {
82         return range.flatten;
83     }
84 }