Reputation: 13
For example, I have the following elements.
vector<int> n = {10, 20, 50, 35, 40, 48, 100};
If I wanted to count how many elements exist within the range of 1 to 30, the answer will be 2 since 10 and 20 is within the 1 to 30 range.
I can do it like this:
vector<int> n = {10, 20, 50, 35, 40, 48, 100};
int counter=0;
for(int x:n){
if(x>=1 && x<=30)
counter++;
}
But is there a way to express the intent more clearly?
Upvotes: 1
Views: 769
Reputation: 2374
You can use a functor
to build a generic solution wherein you don't have to hard code the range.
#include <algorithm>
#include <iostream>
#include <vector>
struct RangeChecker
{
RangeChecker(int min, int max)
: min_{min}
, max_{max}
{}
bool operator()(int value)
{
return value >= min_ && value <= max_;
}
private:
int min_;
int max_;
};
int main()
{
std::vector<int> n = {10, 20, 50, 35, 40, 48, 100};
int count = std::ranges::count_if(n, RangeChecker(1, 30));
std::cout << "count = " << count << std::endl;
int count2 = std::ranges::count_if(n, RangeChecker(1, 50));
std::cout << "count2 = " << count2 << std::endl;
int count3 = std::ranges::count_if(n, RangeChecker(51, 100));
std::cout << "count3 = " << count3 << std::endl;
}
This will produce the following output:
count = 2
count2 = 6
count3 = 1
Upvotes: 0
Reputation: 1438
But is there a better way?
A better way in terms of simplicity, maybe no as it is already simple enough. But in case you are looking for a computationally efficient solution you can use binary search on sorted input.
int main() {
vector<int> n = {0, 10, 20, 30, 50, 35, 40, 48, 100};
sort(n.begin(), n.end());
auto left = lower_bound(n.begin(), n.end(), 1);
auto right = upper_bound(n.begin(), n.end(), 30);
auto count = right - left; // your answer
return count;
}
Upvotes: 2
Reputation: 593
This is in functional style for C++ 20
#include <iostream>
#include <vector>
#include <algorithm>
auto is_in_range(int min, int max) {
return [min, max](int x) { return x >= min && x <= max; };
}
auto in_range(std::vector<int> v, int min, int max) {
return std::count_if(v.begin(), v.end(), is_in_range(min, max));
}
int main() {
auto int_vec = std::vector<int>{10, 20, 50, 35, 40, 48, 100};
std::cout << "count:" << in_range(int_vec, 10, 20) << std::endl;
std::cout << "count:" << in_range({1, 2, 3, 4}, 2, 4) << std::endl;
std::cout << "count:" << in_range({6, 9}, 0, 1) << std::endl;
return 0;
}
output
count:2
count:3
count:0
you can just run it here
Upvotes: 0
Reputation: 2846
In case your input data is unsorted your solution is correct, you can however rewrite it using the more explicit std::count_if
:
int result = std::count_if(n.begin(), n.end(), [](int x) { return x>=1 && x<=30; });
Upvotes: 2
Reputation: 899
There's nothing wrong with your code. If you are looking for fewer lines of code, and you are using C++20, you can do something like this:
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> n = {10, 20, 50, 35, 40, 48, 100};
int counter = std::ranges::count_if(n, [](int x){return x >= 1 && x <= 30;});
std::cout << counter << std::endl;
}
Upvotes: 3