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 }