Finding minimum element based on a transformed value - c++

Here is the task came to me from a code review. I want to select a minimum value from a set, based on a special kind of compare predicate. Like this:
struct Complex { ... };
float calcReduction(Complex elem);
Complex findMinValueWithPredicates(const std::vector<Complex>& values)
{
auto it = std::min_element(values.begin(), values.end(),
[](const Complex& a, const Complex& b) {
return calcReduction(a) < calcReduction(b);
});
if (it == values.end()) throw std::runtime_error("");
return *it;
}
Here I find the minimum element based on a predicate. This predicate computes a reduction of both values to float and then compares those floats. Works fine, looks neat.
Can you see the problem? Yes, for a set of N elements calcReduction() is called 2N times, while it is enough to compute it only N times - once for each element.
One way to solve this problem is to write explicit computations:
Complex findMinValueExplicit(const std::vector<Complex>& values)
{
float minReduction = std::numeric_limits<float>::max();
Complex minValue;
for (Complex value : values)
{
float reduction = calcReduction(value);
if (reduction < minReduction)
{
minReduction = reduction;
minValue = value;
}
}
if (minReduction == std::numeric_limits<float>::max()) throw std::runtime_error("");
return minValue;
}
It works fine and we only have N calls to calcReduction(). However, it looks too verbose and the intent is not such clear, as compared to explicit call of min_element. Because when you call min_element it is really easy to guess you are going to find a minimum element, you know.
The only idea I have for now is to create my own algorithm like min_element_with_reduction, accepting a range and a reduction function. Sounds reasonable, but I wonder whether there are any ready solutions.
Any ideas on how to solve this task with clear intent and some ready solutions? Boost is welcomed. C++17 and ranges are interesting to see.

You could use boost::range library.
auto reductionLambda = [](const Complex& a) { return calcReduction(a); };
auto it = boost::range::min_element(values | boost::adaptors::transformed(
std::ref(reductionLambda));
Ranges themselves should be coming to the standard C++ with C++17 as well.
Edit
As we figured out in comments, this would also make the conversion twice.
So here's something fun:
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/assign.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>
template <class Iterator, class UnaryFunction>
class memoizing_transform_iterator
: public boost::iterator_adaptor<
memoizing_transform_iterator<Iterator, UnaryFunction> // Derived
, Iterator // Base
, std::decay_t<decltype(std::declval<UnaryFunction>()(std::declval<typename Iterator::value_type>()))> // Value
, boost::forward_traversal_tag // CategoryOrTraversal
>
{
public:
memoizing_transform_iterator() {}
explicit memoizing_transform_iterator(Iterator iter, UnaryFunction f)
: memoizing_transform_iterator::iterator_adaptor_(iter), fun(f) {}
static int total;
private:
friend class boost::iterator_core_access;
void increment() { ++this->base_reference(); memoized = false; }
using MemoType = std::decay_t<decltype(std::declval<UnaryFunction>()(std::declval<typename Iterator::value_type>()))>;
MemoType& dereference() const
{
if (!memoized) {
++total;
memoized = true;
memo = fun(*this->base());
}
return memo;
}
UnaryFunction fun;
mutable bool memoized = false;
mutable MemoType memo;
};
template <class Iterator, class UnaryFunction>
auto make_memoizing_transform_iterator(Iterator i, UnaryFunction&& f)
{
return memoizing_transform_iterator<Iterator, UnaryFunction>(i, f);
}
template<class I, class U>
int memoizing_transform_iterator<I, U>::total = 0;
// THIS IS COPIED FROM LIBSTDC++
template<typename _ForwardIterator>
_ForwardIterator
min_el(_ForwardIterator __first, _ForwardIterator __last)
{
if (__first == __last)
return __first;
_ForwardIterator __result = __first;
while (++__first != __last)
if (*__first < *__result)
__result = __first;
return __result;
}
int main(int argc, const char* argv[])
{
using namespace boost::assign;
std::vector<int> input;
input += 2,3,4,1,5,6,7,8,9,10;
auto transformLambda = [](const int& a) { return a*2; };
auto begin_it = make_memoizing_transform_iterator(input.begin(), std::ref(transformLambda));
auto end_it = make_memoizing_transform_iterator(input.end(), std::ref(transformLambda));
std::cout << *min_el(begin_it, end_it).base() << "\n";
std::cout <<begin_it.total;
return 0;
}
Basically I implemented an iterator that memoizes the result of calling the transformation functor. The weird part though is that at least in online compilers, the iterators are copied before their dereferenced values are compared (thus defeating the purpose of memoizing). However when I simply copied the implementation from libstdc++, it works as expected. Perhaps you could try it out on a real machine? The live example is here.
Small edit:
I tested on VS2015 and it works as expected with std::min_element.

Here's a solution using (already works with the range-v3 library, the implementation by the author of the upcoming Ranges TS)
#include <range/v3/all.hpp>
#include <iostream>
#include <limits>
using namespace ranges::v3;
int main()
{
auto const expensive = [](auto x) { static int n; std::cout << n++ << " "; return x; };
auto const v = view::closed_iota(1,10) | view::transform(expensive);
auto const m1 = *min_element(v);
std::cout << "\n" << m1 << "\n";
auto const inf = std::numeric_limits<int>::max();
auto const min = [](auto x, auto y) { return std::min(x, y); };
auto const m2 = accumulate(v, inf, min);
std::cout << "\n" << m2 << "\n";
}
Live On Coliru with output:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1
19 20 21 22 23 24 25 26 27 28
1
As you can see, using min_element takes 2N comparisons, but using accumulate only N.

The only thing missing is the meta-iterator.
A meta-iterator takes an iterator, and creates an iterator that contains a copy of it. It passes all operations through to the contained iterator, except when dereferenced returns a copy of the contained iterator instead.
With any care, the code used for this also works to create an iterator over size_t or int or similar torsor-likes.
template<class It, class R>
struct reduced_t {
It it;
R r;
friend bool operator<( reduced_t const& lhs, reduced_t const& rhs ) {
return lhs.r < rhs.r;
}
};
template<class It, class F>
reduced_t<It, std::result_of_t<F(typename std::iterator_traits<It>::reference)>>
reducer( It it, F&& f ) {
return {it, std::forward<F>(f)(*it)};
}
template<class It, class F>
It reduce( It begin, It end, F&& f ) {
if (begin==end)
return begin;
return std::accumulate(
meta_iterator(std::next(begin)), meta_iterator(end),
reducer(begin, f),
[&](
auto&& reduced, // reduced_t<blah...> in C++11
It i
) {
auto r2 = reducer( i, f );
return (std::min)(reduced, r2);
}
).it;
};
f(*it) is called exactly once per iterator.
I wouldn't call this ... obvious. The trick is that we use accumulate and meta-iterators to implement min_element, then we can have accumulate operate on transformed elements (which gets called once, and returned).
You could rewrite it in stack-based programming style using primitives, but there are lots of primitives to write. Maybe post ranges-v3.
At this point, I'm imagining having some high-powered compositional programming library. If I did, we could do the following:
reducer( X, f ) can be rewritten graph( deref |then| f )(X) using order_by( get_n_t<1> ) for ordering.
The accumulate call could read accumulate( skip_first(range), g(begin(range)), get_least( order_by( get_n_t<1> ) ) ).
Not sure if that is any clearer.

If you take a minElem as a lambda parameter you could use min_element
Complex findMinValueWithPredicates(const std::vector<Complex>& values)
{
float minElem = std::numeric_limits<float>::max();
auto it = std::min_element(values.begin(), values.end(),
[&minElem](const Complex& a, const Complex& b) {
float tmp = calcReduction(a);
if (tmp < minElem) {
minElem = tmp;
return true;
}
return false;
});
if (it == values.end()) throw std::runtime_error("");
return *it;
}
Edit:
Why does this work when bis not used?
25.4.7.21 min_element
21 Returns: The first iterator i in the range [first,last) such that
for every iterator j in the range [first,last) the following
corresponding conditions hold: !(*j < *i) or comp(*j, *i) == false.
Returns last if first == last.
because b should have been named smallestYet (code from cplusplus.com)
template <class ForwardIterator>
ForwardIterator min_element ( ForwardIterator first, ForwardIterator last )
{
if (first==last) return last;
ForwardIterator smallest = first;
while (++first!=last)
if (*first<*smallest) // or: if (comp(*first,*smallest)) for version (2)
smallest=first;
return smallest;
}
Which lead me to a new favourite quote:
"There are only 10 hard problems in Computer Science:
cache invalidation, naming things and off-by-one errors."
one commented on that we might be off-by-one as we don't use b.
I worried that the minElem cached might not be correct.
And I realized that the name b should have been more meaningful as it is "dereferenced iterator to smallest element yet" or smallestYet.
Finally that not all understand binary when its not written with a ´b´ at the end.

Here is another option, but it is still effectively your second solution. To be honest it doesn't look clear, but someone might like it. (I use std::pair<float, Complex> to store reduction result and the value that was reduced.)
std::pair<float, Complex> result{std::numeric_limits<float>::max(), {}};
auto output_function = [&result](std::pair<float, Complex> candidate) {
if (candidate.first < result.first)
result = candidate;
};
std::transform(values.begin(), values.end(),
boost::make_function_output_iterator(output_function),
[](Complex x) { return std::make_pair(calcReduction(x), x); });
P.S. If your calcReduction costs a lot, have you considered caching results in Complex objects? It will lead to a slightly more complicated implementation, but you'll be able to use plain std::min_element which makes your intentions clear.

Related

Is there a c++ std solution to filter and reduce without creating a copy?

I want to find the minimum element of a filtered list. In Python, I would write:
it = (x for x in [1, 8, 4, 3] if x % 2 == 0)
min(it, default=None)
I hoped that the c++ equivalent would read something like:
const std::vector<int> array {1, 8, 4, 3};
const auto arr_end = std::end(array);
auto it = std::find_if(std::begin(array), arr_end, [](int value) { return value % 2 == 0; });
auto jt = std::min_element(it, arr_end);
if (jt != arr_end) {
std::cout << "Min even element is: " << *jt << std::endl;
} else {
std::cout << "No even element exists!" << std::endl;
}
The expected result is 4, but of course the actual result is 3. The reason: find_if skips to 8. Then from 8 to end the min element is chosen, which is 3.
My question: Is there a way to create an iterator over all even values that can be used to find the minimum element? I am not allowed to use boost, create a copy or to write to array. We are using c++17.
There isn't an answer in std as of C++17. In C++20 you can use std::ranges::filter_view, outside of std you can use ranges::filter_view from the range-v3 library, which was the demonstration implementation for the C++20 ranges proposal.
auto filtered = ranges::filter_view(array, [](int value) { return value % 2 == 0; });
auto it = std::min_element(filtered.begin(), filtered.end());
if (it != filtered.end()) {
std::cout << "Min even element is: " << *jt << std::endl;
} else {
std::cout << "No even element exists!" << std::endl;
}
My question: Is there a way to create an iterator over all even values that can be used to find the minimum element?
Yes!
It's slightly unfortunate that you're limited to C++17 with no Boost, because you ideally want ranges - specifically ranges::filter_view etc. which was added in C++20, and preceded by the Boost.Range library.
You may possibly be able to use the intermediate experimental range extension.
If none of those are viable, you can of course write your own filtered_iterator to use with std::min_element.
It's not much fun: although it's probably more reusable (and easier to test) than encoding all the logic into a single lambda, it's a lot of work if you're not planning to reuse it. Also, C++ iterators aren't ideally suited to emulating a Python-style generator, as demonstrated by the redundant end iterator e_ and the copy-assignment operator. You can't elide the end & predicate members of the filtered end iterator either, because both iterators usually need to be the same type.
template <typename BaseIterator, typename UnaryPredicate>
class filter_iterator
{
BaseIterator i_;
BaseIterator e_;
UnaryPredicate pred_;
public:
using reference = typename std::iterator_traits<BaseIterator>::reference;
using value_type = typename std::iterator_traits<BaseIterator>::value_type;
filter_iterator(filter_iterator &&) = default;
filter_iterator(filter_iterator const&) = default;
filter_iterator(BaseIterator i, BaseIterator e, UnaryPredicate p)
: i_(i), e_(e), pred_(p)
{}
filter_iterator& operator=(filter_iterator &&) = default;
filter_iterator& operator=(filter_iterator const& other) {
i_ = other.i_;
e_ = other.e_;
// This is questionable, because we can't copy the predicate without adding
// a level of indirection (ie, always wrapping it in std::function).
// For now, just assume it is stateless for convenience.
return *this;
}
bool operator==(filter_iterator const& other) const
{
return i_ == other.i_;
}
filter_iterator& operator++() {
// We could check i_ is not already e_ here,
// but the caller is required to check this outside anyway
i_ = find_if(next(i_), e_, pred_);
return *this;
}
filter_iterator operator++(int) const {
filter_iterator i(*this);
++i;
return i;
}
reference operator*() { return *i_; }
std::add_const_t<reference> operator*() const { return *i_; }
};
template <typename BaseIterator, typename UnaryPredicate>
bool operator!=(filter_iterator<BaseIterator, UnaryPredicate> const& a,
filter_iterator<BaseIterator, UnaryPredicate> const& b)
{
return !(a == b);
}
Then the wrapper function hides most of this ugliness for us:
template <typename BaseIterator, typename UnaryPredicate>
std::pair<filter_iterator<BaseIterator, UnaryPredicate>,
filter_iterator<BaseIterator, UnaryPredicate>>
filter(BaseIterator b, BaseIterator e, UnaryPredicate p)
{
using f = filter_iterator<BaseIterator, UnaryPredicate>;
auto fbegin = find_if(b, e, p);
return {f{fbegin, e, p}, {e, e, p}};
}
and we can use it like:
int main() {
std::vector<int> a {7, 1, 8, 4, 3, 2};
auto be = filter(a.begin(), a.end(),
[](int i){ return (i%2) == 0;});
auto min = std::min_element(be.first, be.second);
return *min;
}
If you are limited at c++17 there is no solution without making a copy.
If you can transition to C++ 20 the solution is pretty easy. C++ 20 introduced the std::views concept and added the <ranges> library. The concept of std::view is to not create a copy of the underlying container, and it does not modifies the actual values of the container. Behind the scenes the views are actually iterators(actually it is a bit more but lets stay at the basics)
So in your case you could something like this
const std::vector<int> array {1, 8, 4, 3};
auto isEven = [](auto i) { return i % 2 == 0; };
//This is actually an iterator pair(begin, end)
//No copies of the container ever made, the container does not change
auto filtered = array | std::views::filter(isEven);
auto min = std::ranges::min_element(filtered );
if (min != filtered .end())
std::cout << "Min " << *min << std::endl;
else
std::cout << "No min\n";
//You can try to print the vector, it will be unchanged!!!
std::find_if does not filter the vector. It only returns the first element for which the predicate is true. I suppose there is an elegant solution using ranges. The rather inelegant way is to use a custom comparator with min_element:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
const std::vector<int> array {1, 8, 4, 3};
std::vector<float> x;
if (array.size()) {
auto it = std::min_element(begin(array),end(array),
[](auto a, auto b){
if ((a % 2) && (b % 2)) return a < b;
if (a % 2) return false;
if (b % 2) return true;
return a < b;
});
if (*it % 2 == 0) std::cout << *it;
}
}
Odd elements are considered to be not < than other elements. When both are odd or both are even the "normal" < is used. Output is:
4
Note that I have to check if (*it % 2 == 0) because when there is no even element then the call to min_element will return an iterator to the smallest odd element.
PS: The tricky part of custom comparators is to get strict weak ordering correct. The above comparator can be written in a more concise way (thanks to Jarod42) like this:
return std::tuple{ bool{a%2} , a} < std::tuple{ bool{b%2} , b};
Tuples have a operator< that implements a strict weak ordering (given that the elements type provide one), hence writing it this way it is much easier to convice yourself that the comparator really is a strict weak ordering.

How can I avoid "for" loops with an "if" condition inside them with C++?

With almost all code I write, I am often dealing with set reduction problems on collections that ultimately end up with naive "if" conditions inside of them. Here's a simple example:
for(int i=0; i<myCollection.size(); i++)
{
if (myCollection[i] == SOMETHING)
{
DoStuff();
}
}
With functional languages, I can solve the problem by reducing the collection to another collection (easily) and then perform all operations on my reduced set. In pseudocode:
newCollection <- myCollection where <x=true
map DoStuff newCollection
And in other C variants, like C#, I could reduce with a where clause like
foreach (var x in myCollection.Where(c=> c == SOMETHING))
{
DoStuff();
}
Or better (at least to my eyes)
myCollection.Where(c=>c == Something).ToList().ForEach(d=> DoStuff(d));
Admittedly, I am doing a lot of paradigm mixing and subjective/opinion based style, but I can't help but feel that I am missing something really fundamental that could allow me to use this preferred technique with C++. Could someone enlighten me?
IMHO it's more straight forward and more readable to use a for loop with an if inside it. However, if this is annoying for you, you could use a for_each_if like the one below:
template<typename Iter, typename Pred, typename Op>
void for_each_if(Iter first, Iter last, Pred p, Op op) {
while(first != last) {
if (p(*first)) op(*first);
++first;
}
}
Usecase:
std::vector<int> v {10, 2, 10, 3};
for_each_if(v.begin(), v.end(), [](int i){ return i > 5; }, [](int &i){ ++i; });
Live Demo
Boost provides ranges that can be used w/ range-based for. Ranges have the advantage that they don't copy the underlying data structure, they merely provide a 'view' (that is, begin(), end() for the range and operator++(), operator==() for the iterator). This might be of your interest: http://www.boost.org/libs/range/doc/html/range/reference/adaptors/reference/filtered.html
#include <boost/range/adaptor/filtered.hpp>
#include <iostream>
#include <vector>
struct is_even
{
bool operator()( int x ) const { return x % 2 == 0; }
};
int main(int argc, const char* argv[])
{
using namespace boost::adaptors;
std::vector<int> myCollection{1,2,3,4,5,6,7,8,9};
for( int i: myCollection | filtered( is_even() ) )
{
std::cout << i;
}
}
Instead of creating a new algorithm, as the accepted answer does, you can use an existing one with a function that applies the condition:
std::for_each(first, last, [](auto&& x){ if (cond(x)) { ... } });
Or if you really want a new algorithm, at least reuse for_each there instead of duplicating the iteration logic:
template<typename Iter, typename Pred, typename Op>
void
for_each_if(Iter first, Iter last, Pred p, Op op) {
std::for_each(first, last, [&](auto& x) { if (p(x)) op(x); });
}
The idea of avoiding
for(...)
if(...)
constructs as an antipattern is too broad.
It is completely fine to process multiple items that match a certain expression from inside a loop, and the code cannot get much clearer than that. If the processing grows too large to fit on screen, that is a good reason to use a subroutine, but still the conditional is best placed inside the loop, i.e.
for(...)
if(...)
do_process(...);
is vastly preferable to
for(...)
maybe_process(...);
It becomes an antipattern when only one element will match, because then it would be clearer to first search for the element, and perform the processing outside of the loop.
for(int i = 0; i < size; ++i)
if(i == 5)
is an extreme and obvious example of this. More subtle, and thus more common, is a factory pattern like
for(creator &c : creators)
if(c.name == requested_name)
{
unique_ptr<object> obj = c.create_object();
obj.owner = this;
return std::move(obj);
}
This is hard to read, because it isn't obvious that the body code will be executed once only. In this case, it would be better to separate the lookup:
creator &lookup(string const &requested_name)
{
for(creator &c : creators)
if(c.name == requested_name)
return c;
}
creator &c = lookup(requested_name);
unique_ptr obj = c.create_object();
There is still an if within a for, but from the context it becomes clear what it does, there is no need to change this code unless the lookup changes (e.g. to a map), and it is immediately clear that create_object() is called only once, because it is not inside a loop.
Here is a quick relatively minimal filter function.
It takes a predicate. It returns a function object that takes an iterable.
It returns an iterable that can be used in a for(:) loop.
template<class It>
struct range_t {
It b, e;
It begin() const { return b; }
It end() const { return e; }
bool empty() const { return begin()==end(); }
};
template<class It>
range_t<It> range( It b, It e ) { return {std::move(b), std::move(e)}; }
template<class It, class F>
struct filter_helper:range_t<It> {
F f;
void advance() {
while(true) {
(range_t<It>&)*this = range( std::next(this->begin()), this->end() );
if (this->empty())
return;
if (f(*this->begin()))
return;
}
}
filter_helper(range_t<It> r, F fin):
range_t<It>(r), f(std::move(fin))
{
while(true)
{
if (this->empty()) return;
if (f(*this->begin())) return;
(range_t<It>&)*this = range( std::next(this->begin()), this->end() );
}
}
};
template<class It, class F>
struct filter_psuedo_iterator {
using iterator_category=std::input_iterator_tag;
filter_helper<It, F>* helper = nullptr;
bool m_is_end = true;
bool is_end() const {
return m_is_end || !helper || helper->empty();
}
void operator++() {
helper->advance();
}
typename std::iterator_traits<It>::reference
operator*() const {
return *(helper->begin());
}
It base() const {
if (!helper) return {};
if (is_end()) return helper->end();
return helper->begin();
}
friend bool operator==(filter_psuedo_iterator const& lhs, filter_psuedo_iterator const& rhs) {
if (lhs.is_end() && rhs.is_end()) return true;
if (lhs.is_end() || rhs.is_end()) return false;
return lhs.helper->begin() == rhs.helper->begin();
}
friend bool operator!=(filter_psuedo_iterator const& lhs, filter_psuedo_iterator const& rhs) {
return !(lhs==rhs);
}
};
template<class It, class F>
struct filter_range:
private filter_helper<It, F>,
range_t<filter_psuedo_iterator<It, F>>
{
using helper=filter_helper<It, F>;
using range=range_t<filter_psuedo_iterator<It, F>>;
using range::begin; using range::end; using range::empty;
filter_range( range_t<It> r, F f ):
helper{{r}, std::forward<F>(f)},
range{ {this, false}, {this, true} }
{}
};
template<class F>
auto filter( F&& f ) {
return [f=std::forward<F>(f)](auto&& r)
{
using std::begin; using std::end;
using iterator = decltype(begin(r));
return filter_range<iterator, std::decay_t<decltype(f)>>{
range(begin(r), end(r)), f
};
};
};
I took short cuts. A real library should make real iterators, not the for(:)-qualifying pseudo-fascades I did.
At point of use, it looks like this:
int main()
{
std::vector<int> test = {1,2,3,4,5};
for( auto i: filter([](auto x){return x%2;})( test ) )
std::cout << i << '\n';
}
which is pretty nice, and prints
1
3
5
Live example.
There is a proposed addition to C++ called Rangesv3 which does this kind of thing and more. boost also has filter ranges/iterators available. boost also has helpers that make writing the above much shorter.
One style that gets used enough to mention, but hasn't been mentioned yet, is:
for(int i=0; i<myCollection.size(); i++) {
if (myCollection[i] != SOMETHING)
continue;
DoStuff();
}
Advantages:
Doesn't change the indentation level of DoStuff(); when condition complexity increases. Logically, DoStuff(); should be at the top-level of the for loop, and it is.
Immediately makes it clear that the loop iterates over the SOMETHINGs of the collection, without requiring the reader to verify that there is nothing after the closing } of the if block.
Doesn't require any libraries or helper macros or functions.
Disadvantages:
continue, like other flow control statements, gets misused in ways that lead to hard-to-follow code so much that some people are opposed to any use of them: there is a valid style of coding that some follow that avoids continue, that avoids break other than in a switch, that avoids return other than at the end of a function.
for(auto const &x: myCollection) if(x == something) doStuff();
Looks pretty much like a C++-specific for comprehension to me. To you?
If DoStuff() would be dependent on i somehow in the future then I'd propose this guaranteed branch-free bit-masking variant.
unsigned int times = 0;
const int kSize = sizeof(unsigned int)*8;
for(int i = 0; i < myCollection.size()/kSize; i++){
unsigned int mask = 0;
for (int j = 0; j<kSize; j++){
mask |= (myCollection[i*kSize+j]==SOMETHING) << j;
}
times+=popcount(mask);
}
for(int i=0;i<times;i++)
DoStuff();
Where popcount is any function doing a population count ( count number of bits = 1 ). There will be some freedom to put more advanced constraints with i and their neighbors. If that is not needed we can strip the inner loop and remake the outer loop
for(int i = 0; i < myCollection.size(); i++)
times += (myCollection[i]==SOMETHING);
followed by a
for(int i=0;i<times;i++)
DoStuff();
Also, if you don't care reordering the collection, std::partition is cheap.
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
void DoStuff(int i)
{
std::cout << i << '\n';
}
int main()
{
using namespace std::placeholders;
std::vector<int> v {1, 2, 5, 0, 9, 5, 5};
const int SOMETHING = 5;
std::for_each(v.begin(),
std::partition(v.begin(), v.end(),
std::bind(std::equal_to<int> {}, _1, SOMETHING)), // some condition
DoStuff); // action
}
I am in awe of the complexity of the above solutions. I was going to suggest a simple #define foreach(a,b,c,d) for(a; b; c)if(d) but it has a few obvious deficits, for example, you have to remember to use commas instead of semicolons in your loop, and you can't use the comma operator in a or c.
#include <list>
#include <iostream>
using namespace std;
#define foreach(a,b,c,d) for(a; b; c)if(d)
int main(){
list<int> a;
for(int i=0; i<10; i++)
a.push_back(i);
for(auto i=a.begin(); i!=a.end(); i++)
if((*i)&1)
cout << *i << ' ';
cout << endl;
foreach(auto i=a.begin(), i!=a.end(), i++, (*i)&1)
cout << *i << ' ';
cout << endl;
return 0;
}
Another solution in case the i:s are important. This one builds a list that fills in the indexes of which to call doStuff() for. Once again the main point is to avoid the branching and trade it for pipelineable arithmetic costs.
int buffer[someSafeSize];
int cnt = 0; // counter to keep track where we are in list.
for( int i = 0; i < container.size(); i++ ){
int lDecision = (container[i] == SOMETHING);
buffer[cnt] = lDecision*i + (1-lDecision)*buffer[cnt];
cnt += lDecision;
}
for( int i=0; i<cnt; i++ )
doStuff(buffer[i]); // now we could pass the index or a pointer as an argument.
The "magical" line is the buffer loading line that arithmetically calculates wether to keep the value and stay in position or to count up position and add value. So we trade away a potential branch for some logics and arithmetics and maybe some cache hits. A typical scenario when this would be useful is if doStuff() does a small amount of pipelineable calculations and any branch in between calls could interrupt those pipelines.
Then just loop over the buffer and run doStuff() until we reach cnt. This time we will have the current i stored in the buffer so we can use it in the call to doStuff() if we would need to.
One can describe your code pattern as applying some function to a subset of a range, or in other words: applying it to the result of applying a filter to the whole range.
This is achievable in the most straightforward manner with Eric Neibler's ranges-v3 library; although it's a bit of an eyesore, because you want to work with indices:
using namespace ranges;
auto mycollection_has_something =
[&](std::size_t i) { return myCollection[i] == SOMETHING };
auto filtered_view =
views::iota(std::size_t{0}, myCollection.size()) |
views::filter(mycollection_has_something);
for (auto i : filtered_view) { DoStuff(); }
But if you're willing to forego indices, you'd get:
auto is_something = [&SOMETHING](const decltype(SOMETHING)& x) { return x == SOMETHING };
auto filtered_collection = myCollection | views::filter(is_something);
for (const auto& x : filtered_collection) { DoStuff(); }
which is nicer IMHO.
PS - The ranges library is mostly going into the C++ standard in C++20.
I'll just mention Mike Acton, he would definitely say:
If you have to do that, you have a problem with your data. Sort your data!

Is there a way to iterate over at most N elements using range-based for loop?

Is there a nice way to iterate over at most N elements in a container using a range-based for loop and/or algorithms from the standard library (that's the whole point, I know I can just use the "old" for loop with a condition).
Basically, I'm looking for something that corresponds to this Python code:
for i in arr[:N]:
print(i)
As I personally would use either this or this answer (+1 for both), just for increasing your knowledge - there are boost adapters you can use. For your case - the sliced seems the most appropriate:
#include <boost/range/adaptor/sliced.hpp>
#include <vector>
#include <iostream>
int main(int argc, const char* argv[])
{
std::vector<int> input={1,2,3,4,5,6,7,8,9};
const int N = 4;
using boost::adaptors::sliced;
for (auto&& e: input | sliced(0, N))
std::cout << e << std::endl;
}
One important note: N is required by sliced to be not greater than distance(range) - so safer(and slower) version is as follows:
for (auto&& e: input | sliced(0, std::min(N, input.size())))
So - once again - I would use simpler, old C/C++ approach (this you wanted to avoid in your question ;)
Here is the cheapest save solution that works for all forward iterators I could come up with:
auto begin = std::begin(range);
auto end = std::end(range);
if (std::distance(begin, end) > N)
end = std::next(begin,N);
This might run through the range almost twice, but I see no other way to get the length of the range.
You can use the good old break to manually break a loop when needed. It works even with range based loop.
#include <vector>
#include <iostream>
int main() {
std::vector<int> a{2, 3, 4, 5, 6};
int cnt = 0;
int n = 3;
for (int x: a) {
if (cnt++ >= n) break;
std::cout << x << std::endl;
}
}
C++ is great since you can code your own hideous solutions and hide them under an abstraction layer
#include <vector>
#include <iostream>
//~-~-~-~-~-~-~- abstraction begins here ~-~-~-~-~-//
struct range {
range(std::vector<int>& cnt) : m_container(cnt),
m_end(cnt.end()) {}
range& till(int N) {
if (N >= m_container.size())
m_end = m_container.end();
else
m_end = m_container.begin() + N;
return *this;
}
std::vector<int>& m_container;
std::vector<int>::iterator m_end;
std::vector<int>::iterator begin() {
return m_container.begin();
}
std::vector<int>::iterator end() {
return m_end;
}
};
//~-~-~-~-~-~-~- abstraction ends here ~-~-~-~-~-//
int main() {
std::vector<int> a{11, 22, 33, 44, 55};
int n = 4;
range subRange(a);
for ( int i : subRange.till(n) ) {
std::cout << i << std::endl; // prints 11, then 22, then 33, then 44
}
}
Live Example
The above code obviously lacks some error checking and other adjustments, but I wanted to just express the idea clearly.
This works since range-based for loops produce code similar to the following
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
cfr. begin_expr and end_expr
If your container doesn't have (or might not have) RandomAccessIterator, there is still a way to skin this cat:
int cnt = 0;
for(auto it=container.begin(); it != container.end() && cnt < N ; ++it,++cnt) {
//
}
At least for me, it is very readable :-). And it has O(N) complexity regardless of container type.
This is an index iterator. Mostly boilerplate, leaving it out, because I'm lazy.
template<class T>
struct indexT
//: std::iterator< /* ... */ > // or do your own typedefs, or don't bother
{
T t = {};
indexT()=default;
indexT(T tin):t(tin){}
indexT& operator++(){ ++t; return *this; }
indexT operator++(int){ auto tmp = *this; ++t; return tmp; }
T operator*()const{return t;}
bool operator==( indexT const& o )const{ return t==o.t; }
bool operator!=( indexT const& o )const{ return t!=o.t; }
// etc if you want full functionality.
// The above is enough for a `for(:)` range-loop
};
it wraps a scalar type T, and on * returns a copy. It also works on iterators, amusingly, which is useful here, as it lets us inherit effectively from a pointer:
template<class ItA, class ItB>
struct indexing_iterator:indexT<ItA> {
ItB b;
// TODO: add the typedefs required for an iterator here
// that are going to be different than indexT<ItA>, like value_type
// and reference etc. (for simple use, not needed)
indexing_iterator(ItA a, ItB bin):ItA(a), b(bin) {}
indexT<ItA>& a() { return *this; }
indexT<ItA> const& a() const { return *this; }
decltype(auto) operator*() {
return b[**a()];
}
decltype(auto) operator->() {
return std::addressof(b[**a()]);
}
};
The indexing iterator wraps two iterators, the second of which must be random-access. It uses the first iterator to get an index, which it uses to look up a value from the second.
Next, we have is a range type. A SFINAE-improved one can be found many places. It makes iterating over a range of iterators in a for(:) loop easy:
template<class Iterator>
struct range {
Iterator b = {};
Iterator e = {};
Iterator begin() { return b; }
Iterator end() { return e; }
range(Iterator s, Iterator f):b(s),e(f) {}
range(Iterator s, size_t n):b(s), e(s+n) {}
range()=default;
decltype(auto) operator[](size_t N) { return b[N]; }
decltype(auto) operator[] (size_t N) const { return b[N]; }\
decltype(auto) front() { return *b; }
decltype(auto) back() { return *std::prev(e); }
bool empty() const { return begin()==end(); }
size_t size() const { return end()-begin(); }
};
Here are helpers to make working with ranges of indexT easy:
template<class T>
using indexT_range = range<indexT<T>>;
using index = indexT<size_t>;
using index_range = range<index>;
template<class C>
size_t size(C&&c){return c.size();}
template<class T, std::size_t N>
size_t size(T(&)[N]){return N;}
index_range indexes( size_t start, size_t finish ) {
return {index{start},index{finish}};
}
template<class C>
index_range indexes( C&& c ) {
return make_indexes( 0, size(c) );
}
index_range intersect( index_range lhs, index_range rhs ) {
if (lhs.b.t > rhs.e.t || rhs.b.t > lhs.b.t) return {};
return {index{(std::max)(lhs.b.t, rhs.b.t)}, index{(std::min)(lhs.e.t, rhs.e.t)}};
}
ok, almost there.
index_filter_it takes a range of indexes and a random access iterator, and makes a range of indexed iterators into that random access iterator's data:
template<class R, class It>
auto index_filter_it( R&& r, It it ) {
using std::begin; using std::end;
using ItA = decltype( begin(r) );
using R = range<indexing_iterator<ItA, It>>;
return R{{begin(r),it}, {end(r),it}};
}
index_filter takes an index_range and a random access container, intersects their indexes, then calls index_filter_it:
template<class C>
auto index_filter( index_range r, C& c ) {
r = intersect( r, indexes(c) );
using std::begin;
return index_filter_it( r, begin(c) );
}
and now we have:
for (auto&& i : index_filter( indexes(0,6), arr )) {
}
and viola, we have a large musical instrument.
live example
Fancier filters are possible.
size_t filter[] = {1,3,0,18,22,2,4};
using std::begin;
for (auto&& i : index_filter_it( filter, begin(arr) ) )
will visit 1, 3, 0, 18, 22, 2, 4 in arr. It does not, however, bounds-check, unless arr.begin()[] bounds-checks.
There are probably errors in the above code, and you should probably just use boost.
If you implement - and [] on indexT, you can even daisy chain these ranges.
Since C++20 you can add the range adaptor std::views::take from the Ranges library to your range-based for loop. This way you can implement a similar solution to the one in PiotrNycz's answer, but without using Boost:
int main() {
std::vector<int> v {1, 2, 3, 4, 5, 6, 7, 8, 9};
const int N = 4;
for (int i : v | std::views::take(N))
std::cout << i << std::endl;
return 0;
}
The nice thing about this solution is that N may be larger than the size of the vector. This means, for the example above, it is safe to use N = 13; the complete vector will then be printed.
Code on Wandbox
This solution doesn't go past end(), has O(N) complexity for std::list (doesn't use std::distance) works with std::for_each, and only requires ForwardIterator:
std::vector<int> vect = {1,2,3,4,5,6,7,8};
auto stop_iter = vect.begin();
const size_t stop_count = 5;
if(stop_count <= vect.size())
{
std::advance(stop_iter, n)
}
else
{
stop_iter = vect.end();
}
std::for_each(vect.vegin(), stop_iter, [](auto val){ /* do stuff */ });
The only thing it doesn't do is work with InputIterator such as std::istream_iterator - you'll have to use external counter for that.
First we write an iterator which stops at a given index:
template<class I>
class at_most_iterator
: public boost::iterator_facade<at_most_iterator<I>,
typename I::value_type,
boost::forward_traversal_tag>
{
private:
I it_;
int index_;
public:
at_most_iterator(I it, int index) : it_(it), index_(index) {}
at_most_iterator() {}
private:
friend class boost::iterator_core_access;
void increment()
{
++it_;
++index_;
}
bool equal(at_most_iterator const& other) const
{
return this->index_ == other.index_ || this->it_ == other.it_;
}
typename std::iterator_traits<I>::reference dereference() const
{
return *it_;
}
};
We can now write an algorithme for making a rage of this iterator from a given range:
template<class X>
boost::iterator_range<
at_most_iterator<typename X::iterator>>
at_most(int i, X& xs)
{
typedef typename X::iterator iterator;
return std::make_pair(
at_most_iterator<iterator>(xs.begin(), 0),
at_most_iterator<iterator>(xs.end(), i)
);
}
Usage:
int main(int argc, char** argv)
{
std::vector<int> xs = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for(int x : at_most(5, xs))
std::cout << x << "\n";
return 0;
}

Sorting just two elements using STL

Quite often I have two variables foo1 and foo2 which are numeric types. They represent the bounds of something.
A user supplies values for them, but like a recalcitrant musician, not necessarily in the correct order!
So my code is littered with code like
if (foo2 < foo1){
std::swap(foo2, foo1);
}
Of course, this is an idiomatic sort with two elements not necessarily contiguous in memory. Which makes me wonder: is there a STL one-liner for this?
I suggest to take a step back and let the type system do the job for you: introduce a type like Bounds (or Interval) which takes care of the issue. Something like
template <typename T>
class Interval {
public:
Interval( T start, T end ) : m_start( start ), m_end( end ) {
if ( m_start > m_end ) {
std::swap( m_start, m_end );
}
}
const T &start() const { return m_start; }
const T &end() const { return m_end; }
private:
T m_start, m_end;
};
This not only centralizes the swap-to-sort code, it also helps asserting the correct order very early on so that you don't pass around two elements all the time, which means that you don't even need to check the order so often in the first place.
An alternative approach to avoid the issue is to express the boundaries as a pair of 'start value' and 'length' where the 'length' is an unsigned value.
No, but when you notice you wrote the same code twice it's time to write a function for it:
template<typename T, typename P = std::less<T>>
void swap_if(T& a, T& b, P p = P()) {
if (p(a, b)) {
using std::swap;
swap(a, b);
}
}
 
std::minmax returns pair of smallest and largest element. Which you can use with std::tie.
#include <algorithm>
#include <tuple>
#include <iostream>
int main()
{
int a = 7;
int b = 5;
std::tie(a, b) = std::minmax({a,b});
std::cout << a << " " << b; // output: 5 7
}
Note that this isn't the same as the if(a < b) std::swap(a,b); version. For example this doesn't work with move-only elements.
if the data type of your value that you're going to compare is not already in c++. You need to overload the comparison operators.
For example, if you want to compare foo1 and foo2
template <class T>
class Foo {
private:
int value; // value
public:
int GetValue() const {
return value;
}
};
bool operator<(const Foo& lhs, const Foo& rhs) {
return (lhs.GetValue() < rhs.GetValue());
}
If your value is some type of int, or double. Then you can use the std::list<>::sort member function.
For example:
std::list<int> integer_list;
int_list.push_back(1);
int_list.push_back(8);
int_list.push_back(9);
int_list.push_back(7);
int_list.sort();
for(std::list<int>::iterator list_iter = int_list.begin(); list_iter != int_list.end(); list_iter++)
{
std::cout<<*list_iter<<endl;
}

Python-like loop enumeration in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
The community reviewed whether to reopen this question 6 months ago and left it closed:
Original close reason(s) were not resolved
Possible Duplicate:
Find position of element in C++11 range-based for loop?
I have a vector and I would like to iterate it and, at the same time, have access to the indexes for each individual element (I need to pass both the element and its index to a function). I have considered the following two solutions:
std::vector<int> v = { 10, 20, 30 };
// Solution 1
for (std::vector<int>::size_type idx = 0; idx < v.size(); ++idx)
foo(v[idx], idx);
// Solution 2
for (auto it = v.begin(); it != v.end(); ++it)
foo(*it, it - v.begin());
I was wondering whether there might be a more compact solution. Something similar to Python's enumerate. This is the closest that I got using a C++11 range-loop, but having to define the index outside of the loop in a private scope definitely seems to be like a worse solution than either 1 or 2:
{
int idx = 0;
for (auto& elem : v)
foo(elem, idx++);
}
Is there any way (perhaps using Boost) to simplify the latest example in such a way that the index gets self-contained into the loop?
Here is some kind of funny solution using lazy evaluation. First, construct the generator object enumerate_object:
template<typename Iterable>
class enumerate_object
{
private:
Iterable _iter;
std::size_t _size;
decltype(std::begin(_iter)) _begin;
const decltype(std::end(_iter)) _end;
public:
enumerate_object(Iterable iter):
_iter(iter),
_size(0),
_begin(std::begin(iter)),
_end(std::end(iter))
{}
const enumerate_object& begin() const { return *this; }
const enumerate_object& end() const { return *this; }
bool operator!=(const enumerate_object&) const
{
return _begin != _end;
}
void operator++()
{
++_begin;
++_size;
}
auto operator*() const
-> std::pair<std::size_t, decltype(*_begin)>
{
return { _size, *_begin };
}
};
Then, create a wrapper function enumerate that will deduce the template arguments and return the generator:
template<typename Iterable>
auto enumerate(Iterable&& iter)
-> enumerate_object<Iterable>
{
return { std::forward<Iterable>(iter) };
}
You can now use your function that way:
int main()
{
std::vector<double> vec = { 1., 2., 3., 4., 5. };
for (auto&& a: enumerate(vec)) {
size_t index = std::get<0>(a);
double& value = std::get<1>(a);
value += index;
}
}
The implementation above is a mere toy: it should work with both const and non-const lvalue-references as well as rvalue-references, but has a real cost for the latter though, considering that it copies the whole iterable object several times. This problem could surely be solved with additional tweaks.
Since C++17, decomposition declarations even allow you to have the cool Python-like syntax to name the index and the value directly in the for initializer:
int main()
{
std::vector<double> vec = { 1., 2., 3., 4., 5. };
for (auto&& [index, value] : enumerate(vec)) {
value += index;
}
}
A C++-compliant compiler decomposes auto&& inferring index as std::size_t&& and value as double&.
As #Kos says, this is such a simple thing that I don't really see the need to simplify it further and would personally just stick to the traditional for loop with indices, except that I'd ditch std::vector<T>::size_type and simply use std::size_t:
for(std::size_t i = 0; i < v.size(); ++i)
foo(v[i], i);
I'm not too keen on solution 2. It requires (kinda hidden) random access iterators which wouldn't allow you to easily swap the container, which is one of the strong points of iterators. If you want to use iterators and make it generic (and possibly incur a performance hit when the iterators are not random access), I'd recommend using std::distance:
for(auto it(v.begin()); it != v.end(); ++it)
foo(*it, std::distance(it, v.begin());
One way is to wrap the loop in a function of your own.
#include <iostream>
#include <vector>
#include <string>
template<typename T, typename F>
void mapWithIndex(std::vector<T> vec, F fun) {
for(int i = 0; i < vec.size(); i++)
fun(vec[i], i);
}
int main() {
std::vector<std::string> vec = {"hello", "cup", "of", "tea"};
mapWithIndex(vec, [](std::string s, int i){
std::cout << i << " " << s << '\n';
} );
}