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;
}
Related
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.
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;
}
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.
In C# if I want to get all elements in a List List1, which don't belong to another List List2 I can do
var result List1.Except(List2);
Is there something equivalent for std::vectors in C++? (C++11 is allowed)
The following populates List3 with the content from List1 that is not in List2. I hope it is what you're looking for:
std::vector<Type> List1, List2;
//
// populate List1 and List2
//
std::vector<Type> List3;
std::copy_if(List1.begin(), List1.end(), std::back_inserter(List3),
[&List2](const Type& arg)
{ return (std::find(List2.begin(), List2.end(), arg) == List2.end());});
Alternatively, this is likely better performing, since you don't have to search the entire list to determine lack of existence. Rather you can get an early "hit" and just move to the next node. Note the logic flip in the predicate:
std::vector<Type> List3;
std::remove_copy_if(List1.begin(), List1.end(), std::back_inserter(List3),
[&List2](const Type& arg)
{ return (std::find(List2.begin(), List2.end(), arg) != List2.end());});
You need to write your own function something like this:
for (auto element : List1)
{
auto it = std::find(List2.begin(), List2.end(), element);
if(it == List2.end())
{
result.push_back(element);
}
}
You should consider if a std::list is the right data structure for that, as it is - at least in C++ - not sorted by default, so in the worst case you will have to iterate size(list2) times through all elements of the list1, using an algorithm like Asha pointed out.
A better approach would be the use of an ordered container, e.g. multiset and use std::set_difference to create a result.
For any arbitrary container you can always use the std::remove_if + container::erase combination:
template <typename Cont, typename FwdIt>
void subtract(Cont& cont, FwdIt first, FwdIt last) {
using std::begin; using std::end;
using const_reference = typename Cont::value_type const&;
cont.erase(std::remove_if(begin(cont), end(cont),
[first, last](const_reference value){
return last != std::find(first, last, value);
}), end(cont));
}
template <typename Cont1, typename Cont2>
void subtract(Cont1& cont1, Cont2 const& cont2) {
using std::begin; using std::end;
subtract(cont1, begin(cont2), end(cont2));
}
In the case of std::list you can overload the subtract function, because std::list has a dedicated remove_if member function:
template <typename T, typename Alloc, typename FwdIt>
void subtract(std::list<T, Alloc>& l, FwdIt first, FwdIt last) {
l.remove_if([first, last](T const& value){
return last != std::find(first, last, value);
});
}
template <typename T, typename Alloc, typename Cont>
void subtract(std::list<T, Alloc>& l, Cont const& cont) {
using std::begin; using std::end;
subtract(l, begin(cont), end(cont));
}
These implementation are generic and make no assumption about the sorting of the sequences.
If only your second container is guaranteed to be sorted, you can use std::binary_seach instead of find.
If both sequences are sorted, you should use std::set_difference.
The iota template function was added to the standard library to fill an iterator range with an increasing sequence of values.
template<typename ForwardIterator, typename Tp>
void
iota(ForwardIterator first, ForwardIterator last, Tp value)
{
for (; first != last; ++first)
{
*first = value;
++value;
}
}
Most other templates in <numeric> have versions that accept user-specified operators.
Having this:
template<typename ForwardIterator, typename Tp, typename Operator>
void
iota(ForwardIterator first, ForwardIterator last, Tp value, Operator op)
{
for (; first != last; ++first)
{
*first = value;
op(value);
}
}
would be convenient if you don't want to (or can't) overload operator++() for Tp. I would find this version more widely usable than the default operator++() version.
<
I suspect the reason is the usual mix of one or more of the following reasons:
No one submitted a proposal
It wasn't considered important enough for this version (which was already huge, and very late)
it fell through the cracks and was forgotten (like copy_if in C++98)
it is easy to replace using std::generate.
With lambdas, the second version doesn't save much, you can just use std::generate.
template<typename ForwardIterator, typename Tp, typename Operator>
void iota(ForwardIterator first, ForwardIterator last, Tp value, Operator op)
{
std::generate(first, last, [&value,&op](){auto v = value; op(value); return v;});
}
In fact, this makes the existing implementation of std::iota very redundant:
template<typename ForwardIterator, typename Tp>
void iota(ForwardIterator first, ForwardIterator last, Tp value)
{
std::generate(first, last, [&value](){return value++;});
}