I want to find the minimum element in an array, but if the minimum element appears more than once, then I want the last occurrence of the element. I used std::min_element() with my comp() function.
vector<int>::iterator it=min_element(input.begin(), input.end(),comp);
cout << *it << endl;
cout << distance(input.begin(), it);
bool comp(int a, int b) {
if (a <= b)
return true;
else
return false;
}
This code is giving an error saying invalid comparator on input 3 3 4.
Give min_element reverse iterators instead:
vector<int>::reverse_iterator it=min_element(input.rbegin(), input.rend(),comp);
Then convert it back to a "normal" iterator iff you need to.
And don't forget to correct your comparator; it needs to be < not <=.
You might abuse of std::minmax_element which returns the last biggest element contrary to std::max_element:
auto last_min_it = std::minmax_element(input.begin(), input.end(), std::greater<>{}).second;
I would probably use reverse iterator with std::min_element, though:
auto min_rev_it = std::min_element(input.rbegin(), input.rend());
If your data are stored in a vector, then the use of a reverse iterator should suffice, as already suggested.
More generally, the Standard Library does not provide a min_element_last function, as also commented in 1. In this respect, a possible implementation of min_element_last may read:
template <typename I>
using ValueType = typename std::iterator_traits<I>::value_type;
template <typename I, typename R>
// I models ForwardIterator
// R models StrictWeakOrdering on ValueType<I>
I min_element_last(I first, I last, R cmp) {
if (first == last) return last;
I curr = first;
++first;
while (first != last) {
if (!cmp(*curr, *first)) {
curr = first;
}
++first;
}
return curr;
}
template <typename I>
// I models ForwardIterator
// ValueType<I> models TotallyOrdered
I min_element_last(I first, I last) {
using T = ValueType<I>;
return min_element_last(first, last, std::less<T>());
}
The advantage would be the possibility of using min_element_last also with iterators that only model the ForwardIterator concept.
Related
I am having 2 iterators range_begin,range_end, which are my container. I need to find all string which start with char prefix.
Here is my code:
template <typename RandomIt>
pair<RandomIt, RandomIt> FindStartsWith(
RandomIt range_begin, RandomIt
range_end,char prefix){
auto it=equal_range(range_begin,range_end,prefix,
[prefix](const string& city){return city[0]==prefix;});
return it;}
For example, for
const vector<string> sorted_strings = {"moscow", "murmansk", "vologda"};
auto it=FindStartsWith(strings.begin(),strings.end(),'m');
I want to get iterator with first on "moscow" and last after "murmansk".
I am getting strange compilier errors. What is wrong and how can I solve this?I cannot write correct lambda comporator.
equal_range expects a comparison function that takes two parameters; you are passing a function taking one.
A heterogeneous call (one where the type of value is not the same as the type elements in the range) requires a comparison function that can take the two types in either order. A lambda won't work in this case as it only has one operator() overload.
Finally, the function must perform a less-than type of comparison, not an equals one. Roughly, equal_range returns a range from the first element for which !(element < value) to the first element for which value < element.
Your errors might be due to strings.begin() and .end() which do not have sorted_. I do not think you should use a template either. Errors aside, I recommend you use a different std function. A simpler solution is to use foreach:
#include <algorithm>
#include <iterator>
#include <list>
#include <string>
#include <utility>
#include <vector>
typedef std::vector<std::string>::const_iterator RandomIt;
std::vector<std::string> FindStartsWith(RandomIt start, RandomIt end, const char prefix) {
std::vector<std::string> result;
std::for_each(start, end, [&](auto city) {
if (city.front() == prefix) {
result.push_back(city);
}
});
return result;
}
int main(int argc, char* argv[]) {
const std::vector<std::string> sorted_strings = { "moscow", "murmansk", "vologda" };
auto prefix_cities = FindStartsWith(sorted_strings.begin(), sorted_strings.end(), 'm');
return 0;
}
Definitely could use a refactor, but I'm assuming you need to implement it in the FindStartsWith for some other reason...
Thanks for posting, this taught me a lot about equal_range :)
ANSWER:
The reason for your compile error is hidden in the implementations of comparators in two functions "lower_bound" and "upper_bound" which call from the main function "equal_range".
EQUAL_RANGE
template<class ForwardIt, class T, class Compare>
pair<ForwardIt,ForwardIt>
equal_range(ForwardIt first, ForwardIt last,
const T& value, Compare comp)
{
return make_pair(lower_bound(first, last, value, comp),
upper_bound(first, last, value, comp));
}
Make attention to how the comparator is caused in each function. Look that comparators are caused by different sequences of arguments and this is the reason for the error.
LOWER_BOUND:
if (comp(*it, value))
UPPER_BOUND:
if (!comp(value, *it))
ADDITIONAL INFOMATION
Below I copied an example of implementations of two functions accordingly.
LOWER_BOUND:
```
template<class ForwardIt, class T, class Compare>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
ForwardIt it;
typename std::iterator_traits<ForwardIt>::difference_type count, step;
count = std::distance(first, last);
while (count > 0) {
it = first;
step = count / 2;
std::advance(it, step);
if (comp(*it, value)) {
first = ++it;
count -= step + 1;
}
else
count = step;
}
return first;
}
```
UPPER_BOUND:
```
template<class ForwardIt, class T, class Compare>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
ForwardIt it;
typename std::iterator_traits<ForwardIt>::difference_type count, step;
count = std::distance(first, last);
while (count > 0) {
it = first;
step = count / 2;
std::advance(it, step);
if (!comp(value, *it)) {
first = ++it;
count -= step + 1;
}
else
count = step;
}
return first;
}
```
SOLUTION
You have two ways to solve this problem (maybe more).
Write two comparators for each function and call each other separatively.
Convert char argument to string, write comparator for strings and call equal_range.
Is there a simpler way to write this, e.g. by using an STL or boost algorithm?
std::vector<int> v { 0, 1, 2, 3 }; // any generic STL container
std::vector<int> result;
std::transform(v.begin(), v.end() - 1, // (0, 1, 2)
v.begin() + 1, // (1, 2, 3)
std::back_inserter(result),
[](int a, int b){ return a + b; }); // any binary function
// result == { 1, 3, 5 }
I propose using a for loop:
for(std::vector::size_type i = 0; i < v.size() - 1; i++)
result.push_back(v[i] + v[i+1])
A more generic loop for bidirectional iterators:
// let begin and end be iterators to corresponding position
// let out be an output iterator
// let fun be a binary function
for (auto it = begin, end_it = std::prev(end); it != end_it; ++it)
*out++ = fun(*it, *std::next(it));
We can go a bit further and write a loop for forward iterators:
if(begin != end) {
for (auto curr = begin,
nxt = std::next(begin); nxt != end; ++curr, ++nxt) {
*out++ = fun(*curr, *nxt);
}
}
Finally, and algorithm for input iterators. However, this one requires that the value type is copyable.
if(begin != end) {
auto left = *begin;
for (auto it = std::next(begin); it != end; ++it) {
auto right = *it;
*out++ = fun(left, right);
left = right;
}
}
The binary version of std::transform can be used.
The std::adjacent_find/std::adjacent_difference algorithms can be abused.
std::adjacent_difference is for exactly this, but as you mentioned, it copies the first element to the result, which you don't want.
Using Boost.Iterator, it's pretty easy to make a back_inserter which throws away the first element.
#include <boost/function_output_iterator.hpp>
template <class Container>
auto mybackinsrtr(Container& cont) {
// Throw away the first element
return boost::make_function_output_iterator(
[&cont](auto i) -> void {
static bool first = true;
if (first)
first = false;
else
cont.push_back(i);
});
}
Then you can #include <boost/range/numeric.hpp> and do this:
std::vector<int> v { 0, 1, 2, 3 }; // any generic STL container
std::vector<int> result;
boost::adjacent_difference(v, mybackinsrtr(result), std::plus<>{}); // any binary function
See it on ideone
When you want your binary function to return a different type (such as a string), the above solution won't work because, even though the insertion cont.push_back(i) is never called for the first copied element, it still must be compiled and it won't go.
So, you can instead make a back_inserter that ignores any elements of a different type than go in the container. This will ignore the first, copied, element, and accept the rest.
template <class Container>
struct ignore_insert {
// Ignore any insertions that don't match container's type
Container& cont;
ignore_insert(Container& c) : cont(c) {}
void operator() (typename Container::value_type i) {
cont.push_back(i);
}
template <typename T>
void operator() (T) {}
};
template <class Container>
auto ignoreinsrtr(Container& cont) {
return boost::make_function_output_iterator(ignore_insert<Container>{cont});
}
Then you can use it similarly.
std::vector<int> v { 0, 1, 2, 3 }; // any generic STL container
std::vector<std::string> result;
boost::adjacent_difference(v, ignoreinsrtr(result), [](int a, int b){ return std::to_string(a+b); });
On ideone
I would write your own algorithm to apply a functor to each pair of elements in the container.
(Shameless blurb) In my ACCU presentation this year, "STL Algorithms – How to Use Them and How to Write Your Own", showed how to write one like this. I called it adjacent_pair (about 25:00 into the video)
template <typename ForwardIterator, typename Func>
void adjacent_pair(ForwardIterator first, ForwardIterator last, Func f)
{
if (first != last)
{
ForwardIterator trailer = first;
++first;
for (; first != last; ++first, ++trailer)
f(*trailer, *first);
}
}
Stephan T. Lavavej has written a nice adjacent_iterator class here:
How do I loop over consecutive pairs in an STL container using range-based loop syntax?
This could also be used here.
Given
std::vector<T> first = /* some given data */, second;
I want to move all elements e which satisfy some condition cond(e) from first to second, i.e. something like
move_if(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::back_inserter(second), [&](T const& e)
{
return cond(e);
});
I wasn't able to establish this with the algorithms library. So, how can I do that?
If the moved-from elements can stay where they are in first, then just use copy_if with move_iterator.
std::copy_if(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::back_inserter(second), cond);
If the moved-from elements should be erased from first, I'd do
// partition: all elements that should not be moved come before
// (note that the lambda negates cond) all elements that should be moved.
// stable_partition maintains relative order in each group
auto p = std::stable_partition(first.begin(), first.end(),
[&](const auto& x) { return !cond(x); });
// range insert with move
second.insert(second.end(), std::make_move_iterator(p),
std::make_move_iterator(first.end()));
// erase the moved-from elements.
first.erase(p, first.end());
Or partition_copy with a move_iterator, followed by assignment:
std::vector<T> new_first;
std::partition_copy(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::back_inserter(second), std::back_inserter(new_first), cond);
first = std::move(new_first);
The reason why move_if doesn't exist is because it would bloat the library. Either use copy_if with move iterator or write it yourself.
copy_if(move_iterator<I>(f), move_iterator<I>(l), out);
Here is an implementation by Jonas_No found at channel9.
template <typename FwdIt, typename Container, typename Predicate>
inline FwdIt move_if(FwdIt first, FwdIt last, Container &cont, Predicate pred)
{
if (first == last)
return last; // Empty so nothing to move
const size_t size = count_if(first, last, pred);
if (size == 0)
return last; // Nothing to move
cont.resize(size);
FwdIt new_end = first;
auto c = cont.begin();
for (auto i = first; i != last; ++i)
{
if (pred(*i)) // Should it move it ?
*c++ = move(*i);
else
*new_end++ = move(*i);
}
return new_end;
}
#T.C. has provided a perfectly working solution. However, at a first glance, one may not understand what the intend of that code is. So, it might be not perfect, but I tend to prefer something like this:
template<class InputIt, class OutputIt, class InputContainer, class UnaryPredicate>
OutputIt move_and_erase_if(InputIt first, InputIt last, InputContainer& c, OutputIt d_first, UnaryPredicate pred)
{
auto dist = std::distance(first, last);
while (first != last)
{
if (pred(*first))
{
*d_first++ = std::move(*first);
first = c.erase(first);
last = std::next(first, --dist);
}
else
{
++first;
--dist;
}
}
return d_first;
}
Given an input sequence, the standard algorithms std::count and std::accumulate count the number of occurances of a specific value (or predicate matches for std::count_if) and the accumulation of a given associative operation (sum, product, Boolean or/and, min/max, string concatenation, etc.), respectively.
What if one wants to know whether an input sequence contains exactly/at least/at most n occurances/matches, or accumulates to a sum of exactly/at least/at most n? The brute-force way would be to compare the result of std::count or std::accumulate against the target n, but that would miss out on an early exit opportunity when the count or accumulation exceeds the target already halfway through the input sequence.
One could e.g. make a count_until as
template<class InputIt, class T, class Pred>
auto count_until(InputIt first, InputIt last, const T& value, Pred pred)
{
auto res = 0;
for (; first != last; ++first)
if (*first == value && pred(++res))
break; // early exit if predicate is satisfied
return std::make_pair(first, res); // iterator and value to allow continuation
}
and from which one could test for equality/at least/at most by using a suitable predicate and comparison against the returned count.
Questions:
is it possible to write count_until (and similarly for accumulate_until) using a combination existing standard algorithms, possibly in combination with a suitable Boost.Iterator?
In particular, I was thinking of a find_if over an accumulate_iterator where the predicate would extract the count or sum from the iterator.
Or do count_until and accumulate_until warrant inclusion as standalone primitives in a future version of the Standard Library?
Edit: I think the most useful formulation is to return a std::pair of an iterator and the count at the point where the predicate is first satisfied. This enables users to continue iterating.
I was thinking of a combination of std::find_if with a state predicate:
(Pred is normal user predicate.)
template<class InputIt, class T, class Pred>
typename iterator_traits<InputIterator>::difference_type
count_until(InputIt begin, InputIt end, const T& value, Pred pred)
{
typename iterator_traits<InputIterator>::difference_type count = 0;
auto internal_pred = [&count, &value, &pred](decltype(*begin) elem) {
return elem == value && pred(++count);
};
std::find_if(begin, end, internal_pred);
return count;
}
template<class InputIt, class T, class Pred>
T accumulate_until(InputIt begin, InputIt end, T value, Pred pred)
{
auto internal_pred = [&value, &pred] (const T& t) {
value += t;
return pred(value);
};
std::find_if(begin, end, internal_pred);
return value;
}
Is there a couple of std::algorithm/lambda function to access the nth element satisfying a given condition. Because std::find_if will access the first one, so is there an equivalend to find the nth one ?
You need to create a stateful predicate that will count the number of instances and then complete when the expected count is reached. Now the problem is that there are no guarantees as of how many times the predicate will be copied during the evaluation of the algorithm, so you need to maintain that state outside of the predicate itself, which makes it a bit ugly, but you can do:
iterator which;
{ // block to limit the scope of the otherwise unneeded count variable
int count = 0;
which = std::find_if(c.begin(), c.end(), [&count](T const & x) {
return (condition(x) && ++count == 6)
});
};
If this comes up frequently, and you are not concerned about performance, you could write a predicate adapter that created a shared_ptr to the count internally and updated it. Multiple copies of the same adapter would share the same actual count object.
Another alternative would be to implement find_nth_if, which could be simpler.
#include <iterator>
#include <algorithm>
template<typename Iterator, typename Pred, typename Counter>
Iterator find_if_nth( Iterator first, Iterator last, Pred closure, Counter n ) {
typedef typename std::iterator_traits<Iterator>::reference Tref;
return std::find_if(first, last, [&](Tref x) {
return closure(x) && !(--n);
});
}
http://ideone.com/EZLLdL
An STL-like function template would be:
template<class InputIterator, class NthOccurence class UnaryPredicate>
InputIterator find_nth_if(InputIterator first, InputIterator last, NthOccurence Nth, UnaryPredicate pred)
{
if (Nth > 0)
while (first != last) {
if (pred(*first))
if (!--Nth)
return first;
++first;
}
return last;
}
And if you absolutely want to use the std::find_if, you could have something like:
template<class InputIterator, class NthOccurence class UnaryPredicate>
InputIterator find_nth_if(InputIterator first, InputIterator last, NthOccurence Nth, UnaryPredicate pred)
{
if (Nth > 0) {
do
first = std::find_if(first, last, pred);
while (!--Nth && ++first != last);
return first;
}
else
return last;
}
David's answer is fine as it is. Let me just point out that the predicate can be abstracted into the iterators by using the Boost.Iterator library, in particular the boost::filter_iterator adaptor, which has the advantage that it can be used for a lot more algorithms as well (counting e.g.):
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/iterator/filter_iterator.hpp>
template<class ForwardIt, class Predicate, class Size>
ForwardIt find_if_nth(ForwardIt first, ForwardIt last, Predicate pred, Size n)
{
auto vb = boost::make_filter_iterator(pred, first, last);
auto const ve = boost::make_filter_iterator(pred, last, last);
while (vb != ve && --n)
++vb;
return vb.base();
}
int main()
{
auto const v = std::vector<int>{ 0, 0, 3, 0, 2, 4, 5, 0, 7 };
auto const n = 2;
auto const pred = [](int i){ return i > 0; };
auto const nth_match = find_if_nth(v.begin(), v.end(), pred, n);
if (nth_match != v.end())
std::cout << *nth_match << '\n';
else
std::cout << "less than n elements in v matched predicate\n";
}
Live example. This will print 2 (the 2nd element > 0, counting starting at 1, so that find_if matches find_if_nth with n==1. If the predicate is changed to i > 10 or if the nth element is changed to n = 6, it will return the end iterator.