To delete multiple elements in array c++ with the shift [duplicate] - c++

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?

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.)

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);

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};

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())

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.

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;

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.

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.

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.

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));

Related

How do you delete an element from an array in C++? [duplicate]

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?
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.)
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);
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};
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())
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.
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;
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.
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.
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.
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));

Resizing array, does this code influence it badly in any way?

I've seen bunch of tutorials and threads, but no-one does this to resize an array. My question is, whether this affects bad something in my program or is there better way to resize it?
//GOAL:Array to become {1,2,4,5,6,7,8,9}
int size=9;
int array[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1];
//ARRAY IS NOW{1, 2, 4, 5, 6, 7, 8, 9, 9}
//GOAL: TO DELETE THAT LAST 9 FROM ARRAY
size=8;
array[size];
//IT SHOULD BE {1,2,4,5,6,7,8,9} now, but does it effect my program in any negative context?
int array[size] declares an array of size elements.
Outside of a declaration, array[size] access element size in array. It does not resize the array. If you do something like that without changing the value of size, it actually tries to access the element after the last element in the array; not a good idea. In this case, since you changed size to be one less than the original, it accesses the last element of the array, which is safe but does not do what you want.
You can not resize an array in C/C++ that is declared on the stack (one allocated on the heap with malloc could be reallocated to a different size, but you'd have trouble copying it as the newly allocated array of the new size is possibly at a completely different memory location; you'd have to save the old one, allocate a new one of the new size, copy the elements you want, and then free the old one.)
If you want something resizeable, you are in C++; use a container (vector, for example, but pick the one that most suits your needs).
And....I just saw arnav-borborah's comment; don't know how I missed that. You can't even declare the array like that, as size is not a compile time constant.
Until size variable is not constexpr, this
int size=9;
int array[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
is Variable length array, which is not part of c++ standard, only extension of some compilers.
Also automatic arrays are not resizeable, they have fixed size since declaration until they goes out of scope.
You should use some STL container, like std::array, std::vector.
std::array needs to know size at compile time, so there is the best approach, std::vector, which is easy to use and resizeable.
// #include<vector>
std::vector<int> array { 1,2,3,4,5,6,7,8,9 }; // Uniform initialization
// Remove last element
array.pop_back(); // 'array' has now only 8 elements (1..8)
EDIT
As mentioned in comments, if you want to remove n-th element in vector, you may do
array.erase(array.begin()+n);
and job is done.
Hugely. say if you have a payload of 1GB and you Array.Resize the destination array in chunks of 10k then most of your application CPU and wait states will be resizing that array.
If you pre-allocate the array to 1GB, populating that array will be orders of magnitude faster. This is because every time you use Array.Resize.
The computer needs to move that memory in its entirety to another location in memory just to add the extra length you resized it by.
But of cause if you are dealing with very small arrays. This effect is not noticeable.

Copy arrays-vectors

This might be too basic, but I would like to ask. I have my code in Java that copies the start array to newStart and assigns the last element to another array.
int[] newStart= Arrays.copyOf(start, start.length + 1);
newStart[start.length] = array[i];
I converted it to my C++ version with vectors as:
vector<int> newStart(5); //Doesnt have to be 5, sth not known
newStart.insert(newStart.end(), start.begin(), start.end());
newStart[start.size()] = array[i];
However, my code doesn't do what I require. That adds the vector one to the other's end, and makes new assignments accordingly. What is the right way to do that?
C++ vectors don't auto-resize on element access (through operator[] nor at method). Replace the last line with either
newStart.push_back(array[i]);
or
newStart.resize(start.size() + 1);
newStart[start.size()] = array[i];
(the former being more efficient, because it does not default-initialize the element first)
I believe Java arrays don't auto-resize either, so I wouldn't expect the Java code to work either (but it will give exception while the C++ code will make daemons fly out of your nose or whatever else nasty the compiler will think of).
Edit: Reading the question again, the code there is actually defined, but the more wrong.
vector<int> newStart(5); //Doesnt have to be 5, sth not known
This statement actually creates a vector that contains 5 (or whatever) default initialized elements, which in case of int is 0. So now you have
{0, 0, 0, 0, 0}
For sake of example let's say start contains {1, 2, 3, 4, 5, 6, 7}.
newStart.insert(newStart.end(), start.begin(), start.end());
vector::insert adds new elements extending the array and moving the following elements as necessary. The insert is before end, so it will append to the vector, resulting in:
{0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7}
I don't think this is what you wanted. It looks like you wanted a copy of start. Which you'd simply create by copy constructing: vector<int> newStart(start).
newStart[start.size()] = array[i];
Now newStart has the initial 5 zeroes and the elements from start, so it's size is start.size() + 5 and therefore it does have index start.size(). It is the 5th element from end. So per above example, this will modify the vector to:
{0, 0, 0, 0, 0, 1, 2, 1, 4, 5, 6, 7}
^
To append start[0] to the end, use push_back as per above.
Also remember, that Java arrays are reference types, where assignment just shares reference to the same array, but C++ vectors are value types where the content is copied on assignment.
I'm a little confused by the mixing of Java and C++. Hopefully one of the explinations below will help.
If you're in C++, vector has an overloaded operator= so you can just type
newvector = oldvector;
and it will copy.
If you're in java, you can use the copy constructor ex:
Vector v2 = new Vector(v1);
Try this:
for (std::vector<int>::iterator it = start.begin() ; it != start.end(); ++it) {
newStart.push_back (*it);
}
Use std::copy algorithm and back_inserter iterator.
Sample code:
#include <iterator>
#include <vector>
#include <algorithm>
int main () {
std::vector<int> src;
std::vector<int> dest;
std::copy(src.begin(),src.end(),back_inserter(dest));
}

assigning vector

how I can assign v[i] to an series of integers ( type of v is vector ) without initially filling inside
Do you mean initializing std::vector to a series of integers?
int i[] = {1, 2, 3, 4, 5};
std::vector<int> myVector(i, i+ (sizeof(i)/sizeof(int)));
If you meant to create a vector of some elements so you can perform the assignment using their index values. Here, the following statement declares and initializes a vector with its elements being default initialized to 0.
std::vector<int> myVector(5); // constructs a vector of size five integers.
for (int x = 0; x < 5; x++)
myVector[x] = i[x]; // assign values using subscript [..]
But I think the even better way to go would be as #CashCow mentioned in his answer.
Also, note that you can also pre-allocate memory to add elements into the vector with avoiding any repeated memory allocations.
For example:
std::vector<int> myVector; // empty vector for integers
myVector.reserve(5); // pre-allocates memory for five integers
for (int i = 0; i < 5; i++) // now, you can add your elements
myVector.push_back(i);
It is usually a good idea to pre-allocate memory if you know the size of elements i.e in case of large number of elements when the performance is an important factor.
If you have anything that has the traits of an iterator you can use vector's assign method:
std::vector<int> v;
v.assign( iterStart, iterEnd );
iterStart should be such that *iterStart is the first value you want to add.
iterEnd should be one past the end, it is a terminating condition
++iter would move you to the next iterator in the input series.
I don't know what you mean by assign v[i] though. You cannot assign an element to a series. If you want to write the series at a location into an existing vector you can use insert instead of assign.
common way of adding items is calling std::vector<>push_back() method.
std::vector<int> myVector;
myVector.push_back(5);
myVector.push_back(10);
myVector.push_back(3);

STL, reducing an array, c++

For a hw assignment, we are to code a reduce routine that looks like:
int reduce(long array[], int size)
//Where array is the array to reduce, and size is the size of the array.
Using STL. My initial thoughts were to create a set, put all items in the set with a comparison, but then I realized that the set I would create would never be usable since the function returns the size of the new set, but not the set itself to be used. So I'm not sure how I'd go about using the STL to reduce an array. Any thoughts? Thanks.
Edited:
Sorry, reduce is just to reduce the array into a sorted array without duplicates.
E.g. {4, 4, 2, 1} -> {1, 2, 4}
Sort the array using std::sort, then apply std::unique on it to remove duplicates. std::unique works only on sorted arrays. Just to simplify matters here is how you get begin and end of a native array:
long* begin = array;
long* end = array + size;
Once you have these two things, you can apply standard algorithms easily. Also, if you need to return the new size(used elements in the array):
long* end_after_unique = unique(...);
return end_after_unique - array;
std::map only allow a single entry and will sort the items for you automatically. The "second" value in your case is a don't care.
std::map<INT32,INT32> mymap;
mymap[i] = array[i];//inserts if not already present