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