1 module nxt.container_algorithm; 2 3 import std.traits : hasMember; 4 5 /** Try to pop first occurrence of `needle` in `haystack` (if any). 6 Returns: `true` iff pop was made, `false` otherwise. 7 */ 8 bool popFirstMaybe(alias pred = "a == b", C, E)(ref C haystack, 9 in E needle) 10 if (hasMember!(C, "length") && 11 hasMember!(C, "popAt")) 12 // TODO activate this restriction 13 // if (hasSlicing!C && 14 // is(ElementType!C == E.init)) 15 { 16 import std.functional : binaryFun; 17 // doesn't work for uncopyable element types: import std.algorithm.searching : countUntil; 18 size_t offset = 0; 19 foreach (const ref e; haystack[]) 20 { 21 if (binaryFun!pred(e, needle)) { break; } 22 offset += 1; 23 } 24 if (offset != haystack.length) 25 { 26 haystack.popAt(offset); 27 return true; 28 } 29 return false; 30 } 31 32 /** Remove element at index `index` in `r`. 33 * 34 * TODO reuse in array*.d 35 * TODO better name removeAt 36 */ 37 void shiftToFrontAt(T)(T[] r, size_t index) 38 @trusted 39 { 40 assert(index + 1 <= r.length); 41 42 // TODO use this instead: 43 // immutable si = index + 1; // source index 44 // immutable ti = index; // target index 45 // immutable restLength = this.length - (index + 1); 46 // moveEmplaceAll(_store.ptr[si .. si + restLength], 47 // _store.ptr[ti .. ti + restLength]); 48 49 // for each element index that needs to be moved 50 foreach (immutable i; 0 .. r.length - (index + 1)) 51 { 52 immutable si = index + i + 1; // source index 53 immutable ti = index + i; // target index 54 import core.lifetime : moveEmplace; 55 moveEmplace(r.ptr[si], // TODO remove `move` when compiler does it for us 56 r.ptr[ti]); 57 } 58 } 59 60 @safe pure nothrow @nogc unittest 61 { 62 int[4] x = [11, 12, 13, 14]; 63 x[].shiftToFrontAt(1); 64 assert(x == [11, 13, 14, 14]); 65 } 66 67 version(unittest) 68 { 69 // import nxt.array_help : s; 70 // import nxt.dbgio; 71 }