Find last element in std::vector which satisfies a condition - c++

I have this requirement to find the last element in the vector which is smaller than a value.
Like find_first_of but instead of first i want last.
I searched and found that there is no find_last_of but there is find_first_of.
Why is that so? Is the standard way is to use find_first_of with reverse iterators?

Use reverse iterators, like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1,2,42,42,63};
auto result = std::find_if(v.rbegin(), v.rend(),
[](int i) { return i == 42; });
std::cout << std::distance(result, v.rend()) << '\n';
}
Live demo.

This is how it is done with reverse iterators:
std::vector<int> vec = {2,3,10,5,7,11,3,6};
//below outputs '3':
std::cout << *(std::find_if(vec.rbegin(), vec.rend(), [](int i) { return i < 4; }));

Just one thing. Be careful with the predicate if you're looking to find the tail-end of the range which includes the predicated element:
int main()
{
std::vector<int> x { 0, 1, 2, 3, 4, 5 };
// finds the reverse iterator pointing at '2'
// but using base() to convert back to a forward iterator
// also 'advances' the resulting forward iterator.
// in effect, inverting the sense of the predicate to 'v >= 3'
auto iter = std::find_if(std::make_reverse_iterator(x.end()),
std::make_reverse_iterator(x.begin()),
[](auto& v) { return v < 3; }).base();
std::copy(iter,
x.end(),
std::ostream_iterator<int>(std::cout, ", "));
}
result:
3, 4, 5,

From ZenXml:
template <class BidirectionalIterator, class T> inline
BidirectionalIterator find_last(const BidirectionalIterator first, const
BidirectionalIterator last, const T& value)
{
for (BidirectionalIterator it = last; it != first;)
//reverse iteration: 1. check 2. decrement 3. evaluate
{
--it; //
if (*it == value)
return it;
}
return last;
}

Related

Validate the return value of copy_if

I would like to check if the return value of std::copy_if is valid.
Something like this
auto it=std::copy_if(s.begin(),s.end(),d.begin(),[&](...){...});
if([it]) // ????
{
// do something
}
The return value of copy_if marks the "one past the end" of the destination range. If you passed a range to copy_if that can hold all of your to-be-copied values then you can dereference everything between the begin of your output range up to it - 1.
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> s{1,2,3,4,5,6,7,8,9,10};
std::vector<int> d(10);
auto ce = std::copy_if(s.begin(),s.end(),d.begin(),[&](int x){ return x > 5; });
for(auto i = d.begin(); i != ce; ++i)
{
std::cout << *i << "\n";
}
}
A variant of #Pixelchemist's answer is to erase from the returned iterator to the end of the destination. This leaves behind only those elements that satisfied the condition.
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> s{1,2,3,4,5,6,7,8,9,10};
std::vector<int> d(10);
auto it = std::copy_if(s.begin(),s.end(),d.begin(),[&](int x){ return x > 5; });
d.erase(it, d.end());
for(int i : d)
{
std::cout << i << "\n";
}
}
copy_if returns a pointer one past the element it last copied. So in your case the destination range would be [d.begin(), it).
Not sure what type of error checking you would want to do but you can for example use the pointers to see how many elements were copied:
unsigned int elementsCopied = it - d.begin();
You can also iterate over the elements copied:
for(auto i = d.begin(); i != it; ++i)
{
//perform action on i
}
If you are still unsure about how copy_if works, c++ reference gives a clear explanation in my opinion.
Perhaps also interesting, this is a possible implementation of copy_if so you can see what is going on:
template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator copy_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred)
{
while (first!=last) {
if (pred(*first)) {
*result = *first;
++result;
}
++first;
}
return result;
}

std::find_if on std::vector of custom objects with duplicate data

Consider the following scenario:
typedef struct myStruct
{
int cn;
std::string dn;
} MyStruct;
int main()
{
std::vector<MyStruct> v;
// fill some data
...
...
int c = 1;
std::vector<MyStruct>::iterator it = std::find_if(v.begin(), v.end(),
[c](const MyStruct& m) -> bool { return m.cn == c; });
// use 'it' to do stuff
}
If v contains MyStruct objects such that the member variable cn has a value c (=1) in more than one entries, how to handle that scenario? As std::find_if() returns an iterator to the first element in the range, what about the rest?
find_if find first element in range and returns iterator to it. For find all you can either write loop, that will search each-time from it:
std::vector<MyStruct>::iterator it = v.begin();
while (it != v.end())
{
it = std::find_if(it, v.end(),
[c](const MyStruct& m) -> bool { return m.cn == c; });
if (it != v.end())
{
// process founded item
++it;
}
}
or you can sort your sequence and use equal_range algorithm, that will return std::pair of iterators.
With the current Standard library, you have to write a either a loop over std::find_if with a predicate (lambda if you can use C++11/14), or use std::copy_if to copy every match to a new sequence.
When the Ranges proposal becomes available (in a Technical Specification along with C++17), things get much easier, e.g. you will be able to write one single chain of composable views and actions:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
using namespace ranges;
int main()
{
auto const is_even = [](auto x) { return x % 2 == 0; };
auto const print = [&](auto x) { std::cout << x << ","; return x; };
std::vector<int> v { 1, 11, 42, 57, 63, 72 };
v | view::filter(is_even) | action::transform(print);
}
Live On Coliru (already works with the range-v3 library).

How do iterators map/know their current position or element

Consider the following code example :
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
int main()
{
std::vector<int> v(10, 2);
std::partial_sum(v.cbegin(), v.cend(), v.begin());
std::cout << "Among the numbers: ";
std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
std::cout << "All numbers are even\n";
}
if (std::none_of(v.cbegin(), v.cend(), std::bind(std::modulus<int>(),
std::placeholders::_1, 2))) {
std::cout << "None of them are odd\n";
}
struct DivisibleBy
{
const int d;
DivisibleBy(int n) : d(n) {}
bool operator()(int n) const { return n % d == 0; }
};
if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7))) {
std::cout << "At least one number is divisible by 7\n";
}
}
If we look at this part of the code :
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
std::cout << "All numbers are even\n";
}
which is fairly easy to understand. It iterates over those vector elements , and finds out i%2==0 , whether they are completely divisible by 2 or not , hence finds out they're even or not.
Its for loop counterpart could be something like this :
for(int i = 0; i<v.size();++i){
if(v[i] % 2 == 0) areEven = true; //just for readablity
else areEven = false;
}
In this for loop example , it is quiet clear that the current element we're processing is i since we're actually accessing v[i]. But how come in iterator version of same code , it maps i or knows what its current element is that we're accessing?
How does [](int i){ return i % 2 == 0; }) ensures/knows that i is the current element which iterator is pointing to.
I'm not able to makeout that without use of any v.currently_i_am_at_this_posiition() , how is iterating done. I know what iterators are but I'm having a hard time grasping them. Thanks :)
Iterators are modeled after pointers, and that's it really. How they work internally is of no interest, but a possible implementation is to actually have a pointer inside which points to the current element.
Iterating is done by using an iterator object
An iterator is any object that, pointing to some element in a range of
elements (such as an array or a container), has the ability to iterate
through the elements of that range using a set of operators (with at
least the increment (++) and dereference (*) operators).
The most obvious form of iterator is a pointer: A pointer can point to
elements in an array, and can iterate through them using the increment
operator (++).
and advancing it through the set of elements. The std::all_of function in your code is roughly equivalent to the following code
template< class InputIt, class UnaryPredicate >
bool c_all_of(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first) {
if (!p(*first)) {
return false; // Found an odd element!
}
}
return true; // All elements are even
}
An iterator, when incremented, keeps track of the currently pointed element, and when dereferenced it returns the value of the currently pointed element.
For teaching's and clarity's sake, you might also think of the operation as follows (don't try this at home)
bool c_all_of(int* firstElement, size_t numberOfElements, std::function<bool(int)> evenTest)
{
for (size_t i = 0; i < numberOfElements; ++i)
if (!evenTest(*(firstElement + i)))
return false;
return true;
}
Notice that iterators are a powerful abstraction since they allow consistent elements access in different containers (e.g. std::map).

Pick out the least recurring number in an array

I need help picking out the least recurring element in an array. I can't think of any robust algorithm, is there any function defined in the c++ library that does that?
If there is an algorithm that you can come up with, please share. Not the code necessarily, but the idea
'Define least recurring' - suppose an array say a[4] holds 2,2,2,4. 4 is the least recurring element
Uses some C++14 features for brevity but easily adapted to C++11:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
template <typename I>
auto leastRecurring(I first, I last) {
unordered_map<iterator_traits<I>::value_type, size_t> counts;
for_each(first, last, [&counts](auto e) { ++counts[e]; });
return min_element(begin(counts), end(counts), [](auto x, auto y) { return x.second < y.second; })->first;
}
int main() {
const int a[] = {2, 2, 2, 3, 3, 4};
cout << leastRecurring(begin(a), end(a)) << endl;
}
Using only std goodies (live demo on Coliru):
// Your original vector
auto original = { 2, 2, 2, 4, 4 };
// Sort numbers and remove duplicates (in a copy, because std::unique modifies the contents)
std::vector<int> uniques(original);
std::sort(std::begin(uniques), std::end(uniques));
auto end = std::unique(std::begin(uniques), std::end(uniques));
// Count occurences of each number in the original vector
// The key is the number of occurences of a number, the value is the number
std::map<int, int> population;
for (auto i = uniques.begin(); i != end; ++i) {
population.emplace(std::count(std::begin(original), std::end(original), *i), *i);
}
// The map is sorted by key, therefore the first element is the least recurring
std::cout << population.begin()->second;
Note that in the example you gave, the array is already sorted. If you know that this will always be the case, you can get rid of the call to std::sort.
If two numbers have the same population count, the greater one will be kept.
from collections import Counter
def leastFrequentToken(tokens):
counted = Counter(tokens)
leastFrequent = min(counted, key=counted.get)
return leastFrequent
Essentially, create a map of token:count, find the smallest value in the map and return its key.
Assuming the 'numbers' are ints:
// functor to compare k,v pair on value
typedef std::pair<int, size_t> MyPairType;
struct CompareSecond
{
bool operator()(const MyPairType& left, const MyPairType& right) const
{
return left.second < right.second;
}
};
vector<int> tokens[4] = { 2, 2, 2, 4 };
map<int, size_t> counted;
for (vector<int>::iterator i=tokens.begin(); i!=tokens.end(); ++i)
{
++counted[*i];
}
MyPairType min
= *min_element(counted.begin(), counted.end(), CompareSecond());
int leastFrequentValue = min.second;
C++ translation using these SO question answers:
C++ counting instances / histogram using std::map,
Finding minimum value in a Map
in C++11, assuming your type support strict weak ordering (for std::sort), following may help: https://ideone.com/poxRxV
template <typename IT>
IT least_freq_elem(IT begin, IT end)
{
std::sort(begin, end);
IT next = std::find_if(begin, end, [begin](decltype(*begin) el) { return el != *begin; });
IT best_it = begin;
std::size_t best_count = next - begin;
for (IT it = next; it != end; it = next) {
next = std::find_if(it, end, [it](decltype(*begin) el) { return el != *it; });
const std::size_t count = next - it;
if (count < best_count) {
best_count = count;
best_it = it;
}
}
return best_it;
}

Elegant way to find closest value in a vector from above

I need a function that takes a vector (assumed to be sorted), and a value, and returns the closest number that's [edit] greater than less than or equal to that number, preferably using an algorithm from the STL. I have come up with a solution using std::lower_bound(), but it seems kludgy and ugly:
struct ClosestCmp {
bool operator()(const int & x, const int & y) { return x > y; }
};
// vec is assumed to be sorted
int closest(const std::vector<int> & vec, int value)
{
std::vector<int>::const_reverse_iterator cri =
std::lower_bound(vec.rbegin(), vec.rend(), value, ClosestCmp());
if (cri != vec.rend()) {
return *cri;
}
return -1;
}
// ...
vec.push_back(1);
vec.push_back(2);
vec.push_back(4);
vec.push_back(5);
std::cout << closest(vec, 2) << "\n"; // Should ouput "2"
std::cout << closest(vec, 3) << "\n"; // Should ouput "2"
std::cout << closest(vec, 4) << "\n"; // Should ouput "4"
Can anyone suggest a way that's more elegant, maybe using an STL algorithm without needing a comparison function or a reverse iterator? I have looked in the STL, but haven't been able to find a better solution than this.
For reminder:
std::lower_bound: returns the first value that does not compare less
std::upper_bound: returns the first value that compares strictly greater
From your description, std::lower_bound already looks like the perfect fit, what is wrong with:
int closest(std::vector<int> const& vec, int value) {
auto const it = std::lower_bound(vec.begin(), vec.end(), value);
if (it == vec.end()) { return -1; }
return *it;
}
Which is used as:
int main() {
std::vector<int> vec;
vec.push_back(2);
vec.push_back(4);
std::cout << closest(vec, 2) << "\n";
std::cout << closest(vec, 3) << "\n";
std::cout << closest(vec, 4) << "\n";
}
Output:
2
4
4
Requires C++11:
template<typename InputIterator, typename ValueType>
InputIterator closest(InputIterator first, InputIterator last, ValueType value)
{
return std::min_element(first, last, [&](ValueType x, ValueType y)
{
return std::abs(x - value) < std::abs(y - value);
});
}
You can only use std::lower_bound and std::upper_bound with binary predicates that match the order of the container. So, you can't sort by < and then use a different binary predicate (say <= or >). So your "kludge" is actually the correct thing to do. The sorted vector in reverse is the ordering criteria you want to use to find the element less than or equal to the value. (Otherwise, if you were actually searching for the value greater than or equal to, you could just use std::lower_bound.)
For the largest which is less or equal one can use this function
int closest(std::vector<int> const& vec, int value) {
auto const it = std::lower_bound(vec.begin(), vec.end(), value);
if (it == vec.begin()) { return -1; }
else return *(it - 1);
}