1 module yu.array; 2 3 import core.stdc.string : memcpy; 4 /** 5 * 移除数组中元素,并且数组下标前移。 6 * return: 移除的个数 7 * 注: 对数组的长度不做处理 8 */ 9 size_t arrayRemove(E)(ref E[] ary, auto ref E e) { 10 E tv = E.init; 11 scope void doInitVaule(ref E v){ 12 static if(is(E == struct) && hasElaborateDestructor!E) { 13 destroy(v); 14 } 15 memcpy(&v,&tv,E.sizeof); 16 } 17 size_t rm = 0; 18 size_t site = 0; 19 for (size_t j = site; j < ary.length; ++j) { 20 if (ary[j] != e) { 21 if(site != j) 22 memcpy(&ary[site], &ary[j], E.sizeof); 23 site++; 24 } else { 25 doInitVaule(ary[j]); 26 rm++; 27 } 28 } 29 if(rm > 0) { 30 auto size = ary.length - rm; 31 auto rmed = ary[size .. $]; 32 ary = ary[0..size]; 33 fillWithMemcpy(rmed, tv); 34 } 35 return rm; 36 } 37 38 //from std.experimental.allocator.package; 39 void fillWithMemcpy(T)(void[] array, auto ref T filler) nothrow 40 { 41 import core.stdc.string : memcpy; 42 import std.algorithm.comparison : min; 43 if (!array.length) return; 44 memcpy(array.ptr, &filler, T.sizeof); 45 // Fill the array from the initialized portion of itself exponentially. 46 for (size_t offset = T.sizeof; offset < array.length; ) 47 { 48 size_t extent = min(offset, array.length - offset); 49 memcpy(array.ptr + offset, array.ptr, extent); 50 offset += extent; 51 } 52 } 53 54 unittest { 55 import std.stdio; 56 57 int[] a = [0, 0, 0, 4, 5, 4, 0, 8, 0, 2, 0, 0, 0, 1, 2, 5, 8, 0]; 58 writeln("length a = ", a.length, " a is : ", a); 59 int[] b = a.dup; 60 auto rm = arrayRemove(b, 0); 61 writeln("length b = ", b.length, " b is : ", b); 62 assert(b == [4, 5, 4, 8, 2, 1, 2, 5, 8]); 63 64 int[] c = a.dup; 65 rm = arrayRemove(c, 8); 66 writeln("length c = ", c.length, " c is : ", c); 67 68 assert(c == [0, 0, 0, 4, 5, 4, 0, 0, 2, 0, 0, 0, 1, 2, 5, 0]); 69 70 int[] d = a.dup; 71 rm = arrayRemove(d, 9); 72 writeln("length d = ", d.length, " d is : ", d); 73 assert(d == a); 74 }