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) @trusted 38 { 39 assert(index + 1 <= r.length); 40 41 // TODO use this instead: 42 // immutable si = index + 1; // source index 43 // immutable ti = index; // target index 44 // immutable restLength = this.length - (index + 1); 45 // moveEmplaceAll(_store.ptr[si .. si + restLength], 46 // _store.ptr[ti .. ti + restLength]); 47 48 // for each element index that needs to be moved 49 foreach (immutable i; 0 .. r.length - (index + 1)) 50 { 51 immutable si = index + i + 1; // source index 52 immutable ti = index + i; // target index 53 import core.lifetime : moveEmplace; 54 moveEmplace(r.ptr[si], // TODO remove `move` when compiler does it for us 55 r.ptr[ti]); 56 } 57 } 58 59 @safe pure nothrow @nogc unittest 60 { 61 int[4] x = [11, 12, 13, 14]; 62 x[].shiftToFrontAt(1); 63 assert(x == [11, 13, 14, 14]); 64 }