38

How do I remove an element of an array and shift the remaining elements down. So, if I have an array,

array[]={1,2,3,4,5} 

and want to delete 3 and shift the rest so I have,

array[]={1,2,4,5}

How would I go about this in the least amount of code?

SarpSTA
  • 279
  • 2
  • 15
user103572
  • 489
  • 1
  • 6
  • 9

10 Answers10

53

You just need to overwrite what you're deleting with the next value in the array, propagate that change, and then keep in mind where the new end is:

int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
    array[i] = array[i + 1]; // copy next element left

Now your array is {1, 2, 4, 5, 6, 7, 8, 9, 9}. You cannot delete the extra 9 since this is a statically-sized array, you just have to ignore it. This can be done with std::copy:

std::copy(array + 3, // copy everything starting here
          array + 9, // and ending here, not including it,
          array + 2) // to this destination

In C++11, use can use std::move (the algorithm overload, not the utility overload) instead.

More generally, use std::remove to remove elements matching a value:

// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);

Even more generally, there is std::remove_if.

Note that the use of std::vector<int> may be more appropriate here, as its a "true" dynamically-allocated resizing array. (In the sense that asking for its size() reflects removed elements.)

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • no mention of `copy(iter, iter, iter)` or `move(iter, iter, iter)`? – Mooing Duck Oct 12 '12 at 17:20
  • 2
    @MooingDuck: Back in '09 `move(iter, iter,iter)` didn't exist. :P Steve Jessop mentions it below, it would be (have been) stealing to put it in my answer, imo. – GManNickG Oct 12 '12 at 17:52
  • @GManNickG: steal away -- especially for old questions I think the ideal is for the accepted answer to be good. Sometimes it's a bit cheeky to write an answer that cribs all the best bits of every else's answers, but I'm pretty sure that it's nevertheless approved practice, ISTR a FAQ somewhere actually recommends it. Anything I don't want you to use, I won't post to SO :-) – Steve Jessop Oct 12 '12 at 18:31
22

You can use memmove(), but you have to keep track of the array size yourself:

size_t array_size = 5;
int array[5] = {1, 2, 3, 4, 5};

// delete element at index 2
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int));
array_size--;

In C++, though, it would be better to use a std::vector:

std::vector<int> array;
// initialize array...

// delete element at index 2
array.erase(array.begin() + 2);
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • 2
    Please be aware that memmove() will only work for POD types, while OTOH almost any type can be used with a vector, even those that have a user-defined operator=(). – j_random_hacker May 19 '09 at 14:58
11

std::copy does the job as far as moving elements is concerned:

 #include <algorithm>

 std::copy(array+3, array+5, array+2);

Note that the precondition for copy is that the destination must not be in the source range. It's permissible for the ranges to overlap.

Also, because of the way arrays work in C++, this doesn't "shorten" the array. It just shifts elements around within it. There is no way to change the size of an array, but if you're using a separate integer to track its "size" meaning the size of the part you care about, then you can of course decrement that.

So, the array you'll end up with will be as if it were initialized with:

int array[] = {1,2,4,5,5};
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
6

You can't achieve what you want with arrays. Use vectors instead, and read about the std::remove algorithm. Something like:

std::remove(array, array+5, 3)

will work on your array, but it will not shorten it (why -- because it's impossible). With vectors, it'd be something like

v.erase(std::remove(v.begin(), v.end(), 3), v.end())
zvrba
  • 24,186
  • 3
  • 55
  • 65
  • I guess it's impossible as the memory has already been alocated, so the initial memory block will still contain information about a 5 item array. – Rodrigo May 18 '09 at 20:33
3

Depending on your requirements, you may want to use stl lists for these types of operations. You can iterate through your list until you find the element, and erase the element. If you can't use lists, then you'll have to shift everything yourself, either by some sort of stl algorithm or manually.

PiNoYBoY82
  • 1,618
  • 2
  • 14
  • 17
  • I second the suggestion to use std::list. If you need to remove an element from the middle of a vector, it will require having to shift all the elements following it, which is really expensive (O(n) on average). However, removing an element from the middle of a list as you are traversing over it is a simple, O(1) operation. – newacct May 19 '09 at 07:25
2

If you are most concerned about code size and/or performance (also for WCET analysis, if you need one), I think this is probably going to be one of the more transparent solutions (for finding and removing elements):

unsigned int l=0, removed=0;

for( unsigned int i=0; i<count; i++ ) {
    if( array[i] != to_remove )
        array[l++] = array[i];
    else
        removed++;
}

count -= removed;
JosephH
  • 8,465
  • 4
  • 34
  • 62
2

Just so it be noted: If the requirement to preserve the elements order is relaxed it is much more efficient to replace the element being removed with the last element.

Yuri Feldman
  • 2,354
  • 1
  • 20
  • 23
1

Programming Hub randomly provided a code snippet which in fact does reduce the length of an array

for (i = position_to_remove; i < length_of_array; ++i) {
        inputarray[i] = inputarray[i + 1];
}

Not sure if it's behaviour that was added only later. It does the trick though.

MichaelJP
  • 11
  • 1
0

It reduces length indeed. However, if we speak about int arrays, there is a difference between length and size. Size tells us about a capacity of a given array, how much we can store in it. Length of an array tells us about how many items are there actually.

hyono
  • 1
0

This question is bit old. Try using standard library provided containers. These are designed by experts and very well tested. Moreover future developments of standard library algorithms are designed to suite these standard library containers.

If for some reason you have to stick to array, then try using std::array

std::array<int, 5> array = { 1,2,3,4,5 };

//std::remove - The elements that are not deleted are moved to the front of the array,
//and returns the iterator of the element from where it can be completely erased.
auto itr = std::remove(array.begin(), array.end(), 3);

//New array with new size
std::array<int,4> newArray;

std::copy(array.begin(), itr, newArray.begin());

The same thing can be done without using std::array also. But as said earlier for many other benifits prefer to go with std::array

int array[] = { 1,2,3,4,5 };    
auto itr = std::remove(std::begin(array), std::end(array), 3);    
int newArray[4];    
std::copy(std::begin(array), itr, std::begin(newArray));
Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34