Removing elements from dynamic arrays?
David Medlock
noone at nowhere.com
Tue Oct 31 20:08:51 PST 2006
Chris Nicholson-Sauls wrote:
> Bill Baxter wrote:
>
>> David Medlock wrote:
>>
>>> Bill Baxter wrote:
>>>
>>>> How do I remove an element from a dynamic array?
>>>>
>>>> int[] a = [1,2,3,4,5];
>>>>
>>>> I tried every syntax I could think of:
>>>>
>>>> a[3] = void;
>>>> a[3..4] = void;
>>>> a[3..4] = a[3..3];
>>>> a[3] = [];
>>>> a[3..4] = [];
>>>> delete a[3];
>>>> delete a[3..4];
>>>>
>>>> The last one compiles, but fills a[0] with garbage.
>>>>
>>>> I hope the answer isn't:
>>>>
>>>> a = a[0..3] ~ a[4..length];
>>>>
>>>> Thanks!
>>>> --bb
>>>
>>>
>>>
>>>
>>> From my personal tools library...
>>>
>>> // remove an item from an array
>>> template drop(T)
>>> {
>>> T drop( inout T[] arr, int which )
>>> {
>>> debug if ( which>=arr.length)
>>> throw new Exception(str.format("Attempt to drop position %s
>>> from size %s",which,arr.length));
>>> T result = arr[which];
>>> int max = arr.length-1;
>>> for (; which < max; which++ ) arr[which]=arr[which+1];
>>> arr.length= max;
>>> return result;
>>> }
>>> }
>
>
> Something you might find interesting/indicative -- I wrote a little test
> program to time your function versus that found in Cashew, and with the
> slicing expression above. Output:
>
> # Array length: 10000
> # Iterations removing middle element: 5000
> # ---------- Slice syntax: a[0 .. mid] ~ [mid + 1 .. a.length]
> # <Benchmark array removals> Baseline 3.460000
> # ---------- CashewUtils: a.removeIndex(mid)
> # <Benchmark array removals> Time 2.970000 & 1.164983 versus baseline
> # ---------- Drop: version 1
> # <Benchmark array removals> Time 0.270000 & 12.814815 versus baseline
> # ---------- Drop: version 2
> # <Benchmark array removals> Time 0.390000 & 8.871795 versus baseline
>
> Drop v2 was an attempt of mine at rewriting your .drop() that,
> obviously, falls a little short of the original in performance. I also
> find it odd that Cashew's .removeIndex() is actually timing a little
> master than the slice expression, because that's actually it is: a
> wrapper around that very same expression. *confused* Anyhow, clearly
> your .drop() is running very fast! I actually expected the opposite,
> and am surprised/impressed.
>
> Maybe you should release it into Cashew? ;) And maybe I should put
> more into benchmarking the entire Cashew array module. There might be a
> few more placed it could be sped up.
>
>>>
>>> Even though it returns the array, it modifies it in place.
>>>
>>> -DavidM
>>
>>
>>
>> Thanks David, this seems like the best answer in terms of efficiency,
>> although I suppose the
>> a = a[0..3] ~ a[4..length];
>> could theoretically be pretty similar depending how the compiler
>> implements it.
>>
>>
>> There really should be syntax in the language or at least functions
>> like the above in the standard library for this (and for removing
>> slices).
>
>
> # import cashew.utils.array;
> #
> # int[] foo = ... ;
> # foo.remove(3U);
> # foo.removeRange(2U, 7U);
> # foo.removeSub(foo[1 .. 5]);
> etc.
>
> That's why I maintain those. Hopefully, eventually, it does spawn a
> standard library module. (I'm always looking for ways to further
> optimize them, but I do want to keep them fairly simple.)
>
> -- Chris Nicholson-Sauls
Its public domain. Free to use in any way you wish.
-DavidM
For giggles I posted the conditional version(also public domain):
// remove items based on a predicate. returns number of items removed
template drop_if(T)
{
int drop_if( T[] arr, bool delegate(T)pred )
{
int count = 0, dest=0;
foreach( int index, T val ; arr )
{
if ( pred(val) ) { count++; continue; }
if ( dest !=index ) arr[index] = dest;
dest++;
}
return count;
}
}
More information about the Digitalmars-d-learn
mailing list