Removing multiple elements from array
Ali Çehreli
acehreli at yahoo.com
Fri Dec 20 17:41:59 PST 2013
On 12/20/2013 04:47 PM, aldanor wrote:
> Is there an efficient method to remove elements with multiple
> (compile-time-unknown) indices from an array? I currently do
something like
>
> if (!index.empty)
> foreach (i; index.sort.reverse)
> a = a.remove(i);
That's probably a bug, right? The indexes would probably become off as
the array gets shorter.
> ... which looks a bit awkward.
I am sure others can come up with solutions but I can't think of a way
of doing this Phobos right now. :)
Here is a range that does what you want (not very well tested ;) ):
import std.stdio;
import std.array;
import std.range;
import std.algorithm;
struct SkipIndexes(R, I)
{
alias SortedIndexRange = typeof((I.init).sort.uniq);
R range;
SortedIndexRange indexes;
size_t currentIndex;
this(R range, I indexes, size_t currentIndex = 0)
{
this.range = range;
this.indexes = indexes.sort.uniq;
this.currentIndex = currentIndex;
prime();
}
bool empty() const @property
{
return range.empty;
}
ElementType!R front() const @property
{
return range.front;
}
void prime()
{
while (!empty && !indexes.empty && (indexes.front ==
currentIndex)) {
range.popFront();
indexes.popFront();
++currentIndex;
}
}
void popFront()
{
range.popFront();
++currentIndex;
prime();
}
auto save() @property
{
return this;
}
void report() const
{
writeln(indexes);
writeln(currentIndex);
}
}
auto skipIndexes(R, I)(R range, I skipIndexes, size_t currentIndex = 0)
{
return SkipIndexes!(R, I)(range, skipIndexes, currentIndex);
}
void main()
{
auto arr = [ 0, 1, 2, 3, 4, 5 ];
size_t[] badIndexes = [ 0, 1, 5 ];
auto skipped = arr.skipIndexes(badIndexes);
// skipped is a lazy range:
assert(skipped.equal([ 2, 3, 4 ]));
// arr is untouched at this point:
assert(arr == [ 0, 1, 2, 3, 4, 5 ]);
// To affect it, assign from .array of the lazy range:
arr = skipped.array;
assert(arr == [ 2, 3, 4 ]);
}
Ali
More information about the Digitalmars-d-learn
mailing list