Array remove\delete item or elelmant - page 2

 
honest_knave:
If the order of the array doesn't matter, copy the last index to the index you want removed then resize the whole array to be one smaller.

Well this works if you have ONE AND ONLY ONE element to erase. In that case

1) if the element is one generic in the middle, you copy the last in its position and then resize the array one index shorter,

2) if the element to remove is the very last, well, you copy it into itself and then you remove it resizing.

But what if there are more elements to remove and the last element is one of them?

Let's suppose I have a generic 7 elements array

0123456
e0e1e2e3e4e5e6

and I decide I have to remove e3 and e6.

If you call

Erase(MyArray, 3);

first you copy e6 in e3, then you resize the array, so you have this

012345
e0e1e2e6e4e5

and now if you call

Erase(MyArray, 6);

well you try to copy last element e5 in index 6 and I'm pretty sure your code is about to crash against a NullPointer wall.

It's not simply about copying last element into the one you want to remove, but you have to search ascending for to-remove elements, and descending for not-to-remove elements, making a copy one by one until the two searches cross each other.

Some code is worthing a thousand words:

// let's suppose we already know the indexes to remove and they are stored in a global array
int toRemove[2] = {3, 6}; // of course in real solutions this will be dinamically filled using some calculations :)

int OnInit()
  {
   string myArray[];
   ArrayResize(myArray, 7); // as the example seen before

   for(int i = 0; i < ArraySize(myArray); i++)
      myArray[i] = "e" + IntegerToString(i);
      
      int l = 0; // left index
      int r = ArraySize(myArray) - 1; // right index
      
      while (l < r) {
         if (IsToRemove(l) && !IsToRemove(r)) {
            myArray[l] = myArray[r];
            l++; r--;
         }
         else if (!IsToRemove(l)) l++;
         else if (IsToRemove(r)) r--;
      }

   // when I finish, I can finally resize
   ArrayResize(myArray, ArraySize(myArray) - ArraySize(toRemove));
   
   for (int i = 0; i < ArraySize(myArray); i++)
      Alert(IntegerToString(i) + " contains " + myArray[i]);
    
   //---
   return(INIT_SUCCEEDED);
   }

bool IsToRemove(int index) {

        for (int i = 0; i < ArraySize(toRemove); i++)
                if (index == toRemove[i])
                        return true;
        
        // if no index match
        return false;
}

About the example above, you start your search from left so you first move index l from 0 to 3

012l = 345r = 6
e0e1e2e3e4e5e6

then you find that 3 is to remove but 6 too, so you move index r back to 5

012l = 34r = 56
e0e1e2e3e4e5e6

and now 3 is to remove, but 5 is not, so you can finally copy e5 in 3 and move both indexes

0123l = r = 456
e0e1e2e5e4e5e6

now l < r is not verified, so it exits the while loop and you can cut the array, resizing it as its size (7) less the number of indexes you wanted to remove (2).

And that's it. Try the code with alternative toRemove array combinations and tell me if it works fine.

In alternative, I'm going to propose a solution analogue to the one in comment above using ArrayFree and ArrayCopy:

string myArray[];
ArrayResize(myArray, whatever);

// if you decide who's to remove in a loop
string = tmpArray[];
for (int i = 0; i < ArraySize(myArray); i++) {
        if (!IsToRemove(myArray[i])) { // some generic function deciding whether element is to remove (I enter if not)
                ArrayResize(tmpArray, ArraySize(tmpArray) + 1);
                tmpArray[ArraySize(tmpArray) - 1] = myArray[i];
        } // end if
} // at the end of the for-loop I have a temporary array with only the elements I want to keep

ArrayResize(myArray, ArraySize(tmpArray));
for (int i = 0; i < ArraySize(tmpArray); i++) {
        myArray[i] = tmpArray[i];
}
// I could use ArrayFree and ArrayCopy, but this is more generic purpose if you work with classes, structures and objects and must use some functions to initialize a fresh object

Hope this helps.

Let me know if something's wrong or you have better solutions.

 
AleZzabba: well you try to copy last element e5 in index 6 and I'm pretty sure your code is about to crash against a NullPointer wall.

Not null pointer but array exceeded. Invalid call 6, there are only 6 elements in the array at that point.

  1. Either delete the higher number first.
  2. Or remember that after deleting 3, 6 becomes 5.
Reason: