1 /** 2 Gets the element at index n of a range 3 */ 4 module ddash.range.nth; 5 6 /// 7 unittest { 8 import optional: some, none; 9 import ddash.range.front; 10 assert([1, 2].nth(1).frontOr(1) == 2); 11 assert((int[]).init.nth(1).frontOr(9) == 9); 12 13 assert([1, 2].nth(1) == some(2)); 14 assert((int[]).init.nth(1) == none); 15 16 assert([1, 2, 3].nth!(Yes.wrap)(10) == some(2)); 17 } 18 19 import ddash.common; 20 21 /** 22 Gets the element at index n of array if found, else `none`. 23 24 Params: 25 wrap = If `Yes.wrap`, then we wrap around the edge, else not 26 range = an input range 27 n = which element to return 28 29 Returns 30 The value at the nth index of range or defaultValue i not found 31 32 Since: 33 0.0.1 34 */ 35 auto nth( 36 from!"std.typecons".Flag!"wrap" wrap = from!"std.typecons".No.wrap, 37 Range, 38 )( 39 Range range, 40 size_t n, 41 ) 42 if (from!"std.range".isInputRange!Range) 43 { 44 45 import std.range: empty, walkLength, isRandomAccessRange, ElementType; 46 import std.typecons: Yes; 47 import optional: no, some; 48 49 alias T = ElementType!Range; 50 51 if (range.empty) { 52 return no!T; 53 } 54 auto length = range.walkLength; 55 static if (isRandomAccessRange!Range) 56 { 57 alias get = a => range[a]; 58 } 59 else 60 { 61 import std.range: dropExactly; 62 alias get = a => range 63 .dropExactly(a) 64 .front; 65 } 66 67 static if (wrap == Yes.wrap) 68 { 69 return some!T(get(n % length)); 70 } 71 else 72 { 73 if (n >= length) { 74 return no!T; 75 } 76 return some!T(get(n)); 77 } 78 } 79 80 unittest { 81 import std.algorithm: filter; 82 import optional: some, none; 83 assert([1, 2].nth(1) == some(2)); 84 assert([1, 2].filter!"true".nth(1) == some(2)); 85 assert((int[]).init.nth(1) == none); 86 assert([1, 2].nth!(No.wrap)(2) == none); 87 assert([1, 2].nth!(Yes.wrap)(2) == some(1)); 88 } 89 90 unittest { 91 const(string)[] args = []; 92 static assert(__traits(compiles, { args.nth(0); })); 93 } 94 95 /** 96 Returns `optional` front of range 97 98 Since: 99 - 0.0.1 100 */ 101 alias first = from!"ddash.range".maybeFront; 102 103 /// 104 unittest { 105 import optional: some, none; 106 assert([1, 2].first == some(1)); 107 assert((int[]).init.first == none); 108 } 109 110 /** 111 Returns `optional` end of range 112 113 Since: 114 - 0.0.1 115 */ 116 alias last = from!"ddash.range".maybeBack; 117 118 /// 119 unittest { 120 import optional: some, none; 121 assert([1, 2].last == some(2)); 122 assert((int[]).init.last == none); 123 }