1 /** 2 Returns a slice of a range 3 */ 4 module ddash.range.slicing; 5 6 /// 7 unittest { 8 auto arr = [1, 2, 3, 4, 5]; 9 10 assert(arr.slice(1).equal([2, 3, 4, 5])); 11 assert(arr.slice(0, 0).empty); 12 assert(arr.slice(1, 3).equal([2, 3])); 13 assert(arr.slice(0, -2).equal([1, 2, 3])); 14 15 assert(arr.initial.equal([1, 2, 3, 4])); 16 17 assert(arr.tail.equal([2, 3, 4, 5])); 18 } 19 20 import ddash.common; 21 22 /** 23 Returns a slice of range from start up to, but not including, end 24 25 If end is not provided the whole rest of the range is implied. And if 26 end is a negative number then it's translated to `range.length - abs(end)`.` 27 28 Params: 29 range = the input range to slice 30 start = at which index to start the slice 31 end = which index to end the slice 32 33 Returns: 34 A range 35 36 Since: 37 0.0.1 38 */ 39 auto slice(Range)(Range range, size_t start, int end) { 40 import std.range: drop, take, takeNone, walkLength; 41 if (!end) { 42 return range.takeNone; 43 } 44 size_t absoluteEnd = end; 45 if (end < 0) { 46 absoluteEnd = range.walkLength + end; 47 } 48 return range.drop(start).take(absoluteEnd - start); 49 } 50 51 /// Ditto 52 auto slice(Range)(Range range, size_t start) { 53 import std.range: drop; 54 return range.drop(start); 55 } 56 57 /** 58 Gets all but the first element of a range 59 60 Params: 61 range = an input range 62 63 Returns: 64 A range 65 66 Since: 67 0.0.1 68 */ 69 alias tail = (range) => from!"std.range".drop(range, 1); 70 71 /// 72 unittest { 73 assert((int[]).init.tail.empty); 74 assert([1, 2, 3, 4].tail.equal([2, 3, 4])); 75 } 76 77 /** 78 Gets all but the last element of a range 79 80 Params: 81 range = an input range 82 83 Returns: 84 A range 85 86 Since: 87 0.0.1 88 */ 89 alias initial = (range) => from!"std.range".dropBack(range, 1); 90 91 /// 92 unittest { 93 assert((int[]).init.initial.empty); 94 assert([1, 2, 3, 4].initial.equal([1, 2, 3])); 95 }