can somebody help me with this function: suppose that I need to remove all even numbers from a vector using reference: can I do that? Is the push_back correct or should I use something else?
void evenRemoe(vector<int>& arr) {
for(int i = 0; i < arr.size(); i++) {
if(arr[i] % 2 != 0) {
push_back(arr[i]);
}
}
}
Using push_back adds elements so that's not going to work.
You can use std::erase_if with a functor, like a lambda or other function acting as a unary predicate, to decide what elements that should be removed.
void evenRemoe(std::vector<int>& arr) {
std::erase_if(arr, [](int i) { return i % 2 == 0; });
}
Prior to C++20 you could implement the erase–remove idiom
#include <algorithm>
void evenRemoe(std::vector<int>& arr) {
arr.erase(std::remove_if(arr.begin(), arr.end(),
[](int i) { return i % 2 == 0; }),
arr.end());
}
push_back is a method of std::vector for appending an element to the end of the vector, not removing. What you need is one of the erase methods.
However, you should be careful while erasing elements of the vector you're iterating over. Care must be taken to avoid incrementing the index when you remove the element.
The better way to do this is to use std::remove_if algorithm instead of iterating the vector yourself.
void evenRemove(vector<int>& arr) {
auto it = std::remove_if(arr.begin(), arr.end(),
[](int n) { return (n % 2) == 0; });
arr.erase(it, arr.end());
}
Despite the name, std::remove_if doesn't actually remove any elements from the vector. Instead, it moves the elements that match the predicate (in our case - all even integers) to the end of the vector and returns an iterator pointing to the first of such elements. Therefore, to actually remove the elements you need to call erase with the iterators denoting the tail of the vector that contains the even integers.
No, push_back() is not the correct thing to use. That is meant for adding values, not removing them.
Also, your code is actually looking for odd values, not even values.
You can use std::vector::erase() to remove individual values, eg:
void evenRemoe(vector<int>& arr){
for(size_t i = 0; i < arr.size();){
if (arr[i] % 2 == 0){
arr.erase(arr.begin()+i);
}else{
++i;
}
}
}
Alternatively, consider using the Erase-Remove idiom via std::remove_if() and std::vector::erase(), eg:
#include <algorithm>
void evenRemoe(vector<int>& arr){
arr.erase(
std::remove_if(arr.begin(), arr.end(),
[](int value){ return (value % 2) == 0; }
),
arr.end()
);
}
Or, in C++20, via std::erase_if(), eg:
void evenRemoe(vector<int>& arr){
std::erase_if(arr,
[](int value){ return (value % 2) == 0; }
);
}
From C++20 onwards you can use std::erase_if() , Prior to c++20 erase-remove idiom used to be the solution of this problem.
v.erase(std::remove_if(v.begin(), v.end(), is_even), v.end());
Where is_even is a functor
Remove multiple element from vector using iterator.
Just take care that when we erase using iterator,it goes invalid.
int main(){
vector<int> vec={1,2,3,4,5,6,7,8,9};
for(auto it=vec.begin();it!=vec.end();){
if(*it%2==0)
vec.erase(it);
else
it++;
}
for(auto i:vec){
cout<<i<<" ";
}
return 0;
}
output:1 3 5 7 9
2nd method
int main(){
vector<int> vec={1,2,3,4,5,6,7,8,9};
vec.erase(remove_if(vec.begin(),vec.end(),[](int i){
return i%2==0;
}),vec.end());
for(auto i:vec)
cout<<i<<" ";
return 0;
}
Related
vector<int> cutTheSticks(vector<int> arr) {
vector<int> res;
vector<int>::iterator it;
int i=0, mini=0, c=arr.size();
while(c>0) {
res.push_back(c);
mini=*min_element(arr.begin(),arr.end());
for(i=0;i<arr.size();i++) {
arr[i]-=mini;
}
for(auto it=arr.begin();it!=arr.end();it++) {
i=*it;
if(i==0)
arr.erase(it);
}
c=arr.size();
}
return res;
}
I am running this piece of code in the hackerank portal and not on any system.
The way you are using erase is causing the problem in this case. In fact, you exactly don't need a complex approach like this for the problem.
You can simply sort the array in reverse order and then use pop_back() while last element is 0. It will also help to reduce complexity as then you won't need to call min_element each time. You can directly use arr.back() for the minimum element.
Logic behind my approach:
In each iteration, you are subtracting minimum element from each element. This makes number(s) having the minimum value as 0. Clearly, since the array is sorted in reverse order, these numbers will be in the end of the array. You then want to remove these elements for which pop_back is one of the best available options.
Here is sample code:
vector<int> cutTheSticks(vector<int> arr) {
vector<int> res;
sort(arr.begin(), arr.end(), greater<int>());
while (not arr.empty()) {
res.push_back(arr.size());
for (auto &&i : arr)
i -= arr.back();
while (not (arr.back() or arr.empty()))
arr.pop_back();
}
return res;
}
PS:
If you want to stick with your original algorithm then replace
for (auto it = arr.begin(); it!=arr.end(); it++) {
i = *it;
if(i == 0)
arr.erase(it);
}
with something like:
arr.erase(remove(arr.begin(), arr.end(), 0), arr.end()); // called as erase-remove idiom
or
for (auto it = arr.begin(); it!=arr.end(); /* it++ */) {
i = *it;
if(i == 0)
it = arr.erase(it);
else
++it;
}
This thread may help you: Remove elements of a vector inside the loop.
i am trying to write a code that will delete all the elements if an array has same element at different index . it works fine for one element deletion or elements at odd index i.e 1,3,5 etc but it neglects one element if the consecutive index have same element.
i have just tried this to get my hands on arrays
for(int i=0;i<n;i++) //for deletion
{
if(arr[i]==_delete)
{
arr[i]=arr[i+1];
--n;
}
}
I suggest you use std::vector as a container for your objects.
std::vector<TYPE> vec ;
// initialise vector
You can use
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](const auto & item){return item == _delete;}), vec.end());
Alternatively, you can use std::list. Its list::erase has linear time complexity.
As an additional solution, if you want to deal with built-in C++ arrays, the standard std::remove algorithm can be rewritten like this:
void remove(int _delete) {
int j = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] != _delete) {
arr[j++] = arr[i];
}
}
// update the size!
n = j;
}
It's quite pretty:
We keep in the array the elements we only need, and override the ones in which we are not interested (they can be either equal or not to _delete and start at position j till the end)
Is there any STL function which does this?
For vector:
4 4 5 5 6 7
The expected output should be 2,because of one 6 and 7
Would you be kind to help me count them classic if there is no STL function?
I don't think there is an algorithm for that in STL. You can copy into a multimap or use a map of frequencies as suggested, but it does extra work that's not necessary because your array happens to be sorted. Here is a simple algorithm that counts the number of singular elements i.e. elements that appear only once in a sorted sequence.
int previous = v.front();
int current_count = 0;
int total_singular = 0;
for(auto n : v) {
if(previous == n) // check if same as last iteration
current_count++; // count the elements equal to current value
else {
if(current_count == 1) // count only those that have one copy for total
total_singular++;
previous = n;
current_count = 1; // reset counter, because current changed
}
}
if(current_count == 1) // check the last number
total_singular++;
You could also use count_if with a stateful lambda, but I don't think it'll make the algorithm any simpler.
If performance and memory doesn't matter to you, use std::map (or unordered version) for this task:
size_t count(const std::vector<int>& vec){
std::map<int,unsigned int> occurenceMap;
for (auto i : vec){
occurenceMap[i]++;
}
size_t count = 0U;
for (const auto& pair : occurenceMap){
if (pair.second == 1U){
count++;
}
}
return count;
}
with templates, it can be generalize to any container type and any containee type.
Use std::unique to count the unique entries(ct_u) and then user vector count on the original one (ct_o). Difference ct_o-ct_u would give the answer.
P.S.: this will only work if the identical entries are together in the original vector. If not, you may want to sort the vector first.
Using algorithm:
std::size_t count_unique(const std::vector<int>& v)
{
std::size_t count = 0;
for (auto it = v.begin(); it != v.end(); )
{
auto it2 = std::find_if(it + 1, v.end(), [&](int e) { return e != *it; });
count += (it2 - it == 1);
it = it2;
}
return count;
}
Demo
I am working on a problem where I have to create subvectors from a bigger vector. If the elements in the vector are consecutive I have to create a vector of those elements. If there are elements which are not consecutive then a vector of that single elements is created. My logic is as below
vector<int> vect;
for (int nCount=0; nCount < 3; nCount++)
vect.push_back(nCount);
vect.push_back(5);
vect.push_back(8);
vector<int>::iterator itEnd;
itEnd = std::adjacent_find (vect.begin(), vect.end(), NotConsecutive());
The functor NotConsecutiveis as below
return (int first != int second-1);
So I am expecting the std::adjacent_find will give me back the iterators such that I can create vector one{0,1,2,3}, vector two{5} and vector{8}. But I am not sure if there is any simpler way?
Edit:I forgot to mention that I have std::adjacent_find in a loop as
while(itBegin != vect.end())
{
itEnd = std::adjacent_find (vect.begin(), vect.end(), NotConsecutive());
vector<int> groupe;
if( std::distance(itBegin, itEnd) < 1)
{
groupe.assign(itBegin, itBegin+1);
}
else
{
groupe.assign(itBegin, itEnd);
}
if(boost::next(itEnd) != vect.end())
{
itBegin = ++itEnd;
}
else
{
vector<int> last_element.push_back(itEnd);
}
}
Does it make any sense?
I think this is what is being requested. It does not use adjacent_find() but manually iterates through the vector populating a vector<vector<int>> containing the extracted sub-vectors. It is pretty simple, IMO.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vect { 0, 1, 2, 3, 5, 8 };
// List of subvectors extracted from 'vect'.
// Initially populated with a single vector containing
// the first element from 'vect'.
//
std::vector<std::vector<int>> sub_vectors(1, std::vector<int>(1, vect[0]));
// Iterate over the elements of 'vect',
// skipping the first as it has already been processed.
//
std::for_each(vect.begin() + 1,
vect.end(),
[&](int i)
{
// It the current int is one more than previous
// append to current sub vector.
if (sub_vectors.back().back() == i - 1)
{
sub_vectors.back().push_back(i);
}
// Otherwise, create a new subvector contain
// a single element.
else
{
sub_vectors.push_back(std::vector<int>(1, i));
}
});
for (auto const& v: sub_vectors)
{
for (auto i: v) std::cout << i << ", ";
std::cout << std::endl;
}
}
Output:
0, 1, 2, 3,
5,
8,
See demo at http://ideone.com/ZM9ssk.
Due to the limitations of std::adjacent_find you can't use it quite the way you want to. However it can still be useful.
What you can do is to iterate over the collection, and use std::adjacent_find in a loop, with the last returned iterator (or your outer loop iterator for the first call) until it returns end. Then you will have a complete set of consecutive elements. Then continue the outer loop from where the last call to std::adjacent_find returned a non-end iterator.
Honestly, I don't find any clear disadvantage of using a simple hand-crafted loop instead of standard functions:
void split(const std::vector<int> &origin, vector<vector<int> > &result)
{
result.clear();
if(origin.empty()) return;
result.resize(1);
result[0].push_back(origin[0]);
for(size_t i = 1; i < origin.size(); ++i)
{
if(origin[i] != origin[i-1] + 1) result.push_back(vector<int>());
result.back().push_back(origin[i]);
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can you remove elements from a std::list while iterating through it?
I want to erase items from the list while iterating over. I have done this before, but somehow this simple example fails me. thnx for the help in advance!
#include<iostream>
#include<list>
using namespace std;
void main()
{
list<int> x;
for ( int i =0;i<10; i++)
x.push_back(i);
for( list<int>::iterator k = x.begin(); k != x.end();k++)
cout<<*k<<" ";
cout<<endl;
for( list<int>::iterator k = x.begin(); k != x.end();k++)
{
if ((*k)%2)
{
x.erase(k);
}
}
cout<<endl;
getchar();
}
Just FWIW, what you're talking about can also be done with (for one example) std::list::remove_if:
template <class T>
class odd {
bool operator()(T const &value) {
return value % 2 != 0;
}
};
// ...
x.remove_if(odd);
With C++ 0x and/or Boost lambda, you can do this without defining even separately, which is quite convenient for trivial conditions like this. In theory you could also define this in place with a combination of std::bind1st, std::bind2nd, std::equal and std::modulus -- but (IMO) the result would be sufficiently difficult to decipher that it would be inadvisable.
Note that std::list::remove_if (unlike std::remove_if) actually erases the items you ask to have removed, whereas std::remove_if normally needs to be combined with a call to erase to actually erase the removed items.
erase returns the element after the erased element: http://www.cplusplus.com/reference/stl/vector/erase/
So try something like this:
for( list<int>::iterator k = x.begin(); k != x.end();)
if( (*k)%2 )
k=x.erase(k);
else
++k;
Instead of writing yet another for(;;) loop to iterate over a STL container, the whole thing can usually be done quicker with STL algorithms and lambda expressions.
Your example code can be rewritten as:
list<int> x;
int i = 0;
generate_n(back_inserter(x), 10, [&i](){ return i++; });
copy(x.begin(), x.end(), ostream_iterator<int>(cout, " "));
cout << endl;
x.remove_if([](int n){ return n%2==0; });
Your iterator is invalid when you do so. Do
k = x.erase(k);