So today, I decided to learn vectors. Nothing much. Learned how to read data from file to a vector and all basic vectors functions. So then, I decided to practice all of it. And what I wanted to do first is to remove some elements that are for example greater than 15. Now with an array, it has been easier (probably because I knew how to do it). I would just make a second for loop. However, I don't think it's possible with vectors. But they have .erase function. So I tried it in for loop. But that doesn't work as it supposed to.
The only sense that it's "easier" with an array is that you can't physically do it in the first place; an array has a fixed size.
Using erase like that is error-prone because let's say you're currently at i = 5, and you erase element Skaiciai[5]... so what's now at Skaiciai[5] after the erase? Well, Skaiciai[6] (or perhaps nothing, if you were already at the end of the array).
So in a sense, your current index becomes invalidated when you erase something.
Okay, but let's say that we don't know what to remove yet. Let's say we need to find first the sum of the elements and then it's average. And then remove every element that is lower than average. Since I'm new I don't know how would I change this
bool isLessThan15(int n) { return n < 15; }
Would I just pass the function that calculated the average to this boolean ?
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main()
{
std::vector<int> seq { 12, 24, 58, 67, 92, 45, 77, 22, 56, 89, 21, 80 } ;
for( int v : seq ) std::cout << v << ' ' ;
std::cout << '\n' ;
// find the sum of all the elements
// https://en.cppreference.com/w/cpp/algorithm/accumulateconstdouble sum = std::accumulate( seq.begin(), seq.end(), 0.0 ) ;
constdouble average = sum / seq.size() ; // find the average
std::cout << "average: " << average << '\n' ;
// remove all elements less than average
// https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiomconstauto less_than_avg = [average] ( int v ) { return v < average ; } ;
seq.erase( std::remove_if( seq.begin(), seq.end(), less_than_avg ), seq.end() ) ;
for( int v : seq ) std::cout << v << ' ' ;
std::cout << '\n' ;
}
we need to find first the sum of the elements and then it's average. And then remove every element that is lower than average.
Well, there's many ways to skin this cat. I would still prefer to use remove_if. If I choose to go with the same pattern as before, I could do something like the following. Note that you wouldn't re-calculate the average each time, just once (unless you want it to be a rolling-average or something like that).
Edit: Of course, JLBorges' example, which uses a lambda to capture the average, is much more concise than mine. (I need to get more comfortable with using those...!)
Go to Settings --> Compiler --> Compiler Flags tab, and check "Have g++ follow the C++14 ISO C++ language standard [-std=c++14]". (If -std=c++17 is available, you can also try that. If nothing else, -std=c++11 should be available)
My previous post will compile with -std=c++11 or higher.
Thank you, it worked ! But now I just have questions (so I learn it rather than memorize it)
1 2
constauto less_than_avg = [average] ( int v ) { return v < average ; } ;
seq.erase( std::remove_if( seq.begin(), seq.end(), less_than_avg ), seq.end() ) ;
What does the const auto mean ?
Next thing. Does the less_than_avg get assigned to whatever value is in [average] ? And then there is a new int v, right ? And you use the v to check whether the condition is true or false right ? (just like previously you showed it with the boolean if we know what we want to remove already)
And the .erase function. Why after less_than_avg there's again seq.end() ?
const means constant, a value that cannot be assigned a new value:
const double pi = 3.14; //ok
pi = 2.68; //error, its a constant!
and auto means 'let the compiler determine the type'.
less than average returns the result of a Boolean expression: its true or false.
int v is just a parameter. its a function, just a little different from what you have seen before, called a lambda which are used mostly for one-line functions that are fed into standard algorithms like sort (how to compare values) or the like.
the erase is using less than average to figure out what to erase. Its saying to erase when that is TRUE.
so for everything in the container, erase it if its less than average.
This is advanced, modern style c++ where the language does most of the work (iteration/looping/logic) and you just guide it a bit.