Additional condition in for each - c++

I'm wondering: is there any possibility to add additional condition to for each?
I'm thinking about something like:
int i=0;
for(auto &it : list; i++)
if(it.ID == 25)
return i;
or
for(auto &it : list, int i=0; i++)
if(it.ID == 25)
return i;

You can use std::find_if:
const auto position = std::find_if(list.cbegin(), list.cend(), []((decltype(*list.cbegin()) value)
{
return value.ID == 25;
});
return position - list.cbegin();
(Updated, now independent of container value_type)

No it's not possible. You can use the old "normal" for loop for that:
auto iter = std:begin(list)
for (int i = 0; iter != std::end(list); ++iter, ++i)
{
auto& it = *iter;
// ...
}

Mandatory Reference: Sean Parent's "Seasoning C++" talk:
goal 1: Avoid raw loops
In cases like these, abstract your algorithm!
This will come up more often, so it's worth making it generic:
#include <algorithm>
template <typename C, typename Pred>
size_t index_if(C const& c, Pred&& pred)
{
const auto f(begin(c)), l(end(c));
auto match = std::find_if(f, l, std::forward<Pred>(pred));
return (l==match) ? -1 : std::distance(f, match);
}
Now you can write your query:
int main()
{
struct X { int ID; };
const std::vector<X> v { {1},{2},{3},{25},{4},{5},{6},{42} };
return index_if(v, [](X const& x) { return x.ID == 25; });
}
See it Live on Coliru
PS. You might want a value-based version along with the predicate-based one:
template <typename C, typename V/* = typename C::value_type*/>
size_t index_of(C const& c, V const v)
{
const auto f(begin(c)), l(end(c));
auto match = std::find(f, l, v);
return (l==match) ? -1 : std::distance(f, match);
}

Related

How to look for an element inside a set of sets in C++?

Following is my code:
set<set<int,greater<int>>> output;
set<int,greater<int>> k;
k.insert(5);
output.insert(k);
Now how do I find out if element 5 is present in my 'output' set or not?
And how do I find out which set, inside my 'output' set, the element 5 belongs to?
Use a simple for loop:
size_t ii = 0;
for (const auto& inner : output) {
if (inner.count(5))
std::cout << "found in set " << ii << std::endl;
++ii;
}
There's a pre C++20 and a C++20 (using ranges) solution
Pre-C++20 I'm using std::find_if and set::find.
C++20 I'm using std::ranges::find_if and set::contains.
For the C++20 I'm also using std::optional std::reference_wrapper return type. And concepts, so it's a generic solution applicable to all sets and maps.
#include <set>
#include <algorithm>
template<typename T, typename Comp = std::less<T>>
std::set<T, Comp> const* findInSetOfSets(std::set<std::set<T, Comp>> const& setOfSets, T const& value) {
auto const it = std::find_if(cbegin(setOfSets), cend(setOfSets),
[&](std::set<T, Comp> const& set) { return set.find(value) != end(set); } );
if (it != cend(setOfSets)) return &*it;
return nullptr;
}
#include <optional>
#include <functional>
#include <type_traits>
template<typename T, typename U>
concept hasContains = requires(T& t, U& u) {
{ t.contains(u) } -> std::same_as<bool>;
};
template<std::ranges::input_range R, typename T,
typename U = std::remove_reference<R>::type::value_type>
requires hasContains<U, T>
[[nodiscard]] auto findCpp20(R&& r, T const& value) noexcept
->std::optional<std::reference_wrapper<U const>> {
auto it = std::ranges::find_if(r,
[&](U const& u) { return u.contains(value); } );
if (it != std::ranges::end(r)) return *it;
return std::nullopt;
}
#include <cstdio>
int main(){
std::set<std::set<int,std::greater<int>>> output;
std::set<int,std::greater<int>> k;
k.insert(5);
output.insert(k);
auto setPtr = findInSetOfSets(output, 5);
if (setPtr != nullptr) printf("set found!\n");
auto optionalSet = findCpp20(output, 5);
if (optionalSet.has_value()) printf("set found!\n");
}
godbolt
Here's a boolean function that looks for element p inside a set of sets s
bool findelem(int p, set<set<int>> const& s)
{
for (auto itr1= s.cbegin(); itr1 != s.cend(); ++itr1) {
for (auto itr2 = itr1->cbegin(); itr2 != itr1->cend(); ++itr2) {
if (*itr2==p) {
return true;
}
}
}
return false;
}

Find any element in a map by matching a sub-element of the key

I have a std::map whose key is another class. Like the example below:
class KeyClass
{
public:
int a;
int b;
};
main(){
//some code
std::map<KeyClass, SomeOtherClass> mapVariable;
KeyClass k1(); k1.a = 1; k1.b = 1;
KeyClass k2(); k2.a = 2; k2.b = 2;
mapVariable[k1] = SomeOtherClass();
mapVariable[k2] = SomeOtherClass();
//I am trying something like see if any element is there whose key.a = 1 (or may be key.a = 6 --> will fail here)?
}
I tried looping across mapVariable and checking iter->first.a == 1, but is there anyway I can use the map::count() function to get that?
I am using this in a CLI C++ code, so it seem that I am unable to use a lambda function.
You can use std::find_if() to search the map using a custom predicate, eg:
#include <algorithm>
using myMapType = std::map<KeyClass, SomeOtherClass>;
myMapType mapVariable;
...
auto iter = std::find_if(
mapVariable.begin(), mapVariable.end(),
[](const myMapType::value_type &entry){ return entry.first.a == 1; }
);
if (iter != mapVariable.end()) {
...
}
If using a lambda is not an option, you can use a functor instead:
#include <algorithm>
typedef std::map<KeyClass, SomeOtherClass> myMapType;
struct findKey
{
bool operator()(const myMapType::value_type &entry) const { return entry.first.a == 1; }
};
myMapType mapVariable;
...
myMapType::iterator iter = std::find_if(mapVariable.begin(), mapVariable.end(), findKey());
if (iter != mapVariable.end()) {
...
}
If you don't want to use std::find_if(), you can use a manual loop:
myMapType::iterator iter = mapVariable.begin();
while (iter != mapVariable.end()) {
if (iter->first.a == 1) break;
++iter;
}
if (iter != mapVariable.end()) {
...
}
You can use std::find_if with a lambda:
auto it = std::find_if(mapVariable.begin(), mapVariable.end(), [](const auto& pair) {
return pair.first.a == 1; // first is the key, second is the value
});
Or without using a lambda:
struct Functor {
bool operator()(const decltype(mapVariable)::value_type& pair) const {
return pair.first.a == 1;
}
};
auto it = std::find_if(mapVariable.begin(), mapVariable.end(), Functor{});
Then check if you got a match:
if(it != mapVariable.end()) {
// match found
}
To be able to use the size_type std::map::count( const K& x ) const overload, the comparison function used in the map would need to be transparent.
Example:
struct Compare {
using is_transparent = int;
bool operator()(int x, const KeyClass& b) const {
return x < b.a;
}
bool operator()(const KeyClass& a, int x) const {
return a.a < x;
}
bool operator()(const KeyClass& a, const KeyClass& b) const {
return a.a < b.a;
}
};
//...
std::map<KeyClass, SomeOtherClass, Compare> mapVariable;
//...
if(mapVariable.count(1)) {
// match found
}

Generalization of two methods

Consider the structure:
struct B {int b1, b2;};
struct A {
std::set<B, compBLess> m_setLess;
std::set<B, compBGreater> m_setGreater;
void onFirst(int val) {
auto i_set = m_setLess.begin();
auto comp = [&](){ return val >= i_set->b1; };
while ( i_set != m_setLess.end() && comp() ) {
sameForBoth(*i_set);
++i_set;
}
}
void onSecond(int val) {
auto i_set = m_setGreater.begin();
auto comp = [&](){ return val <= i_set->b1; };
while ( i_set != m_setGreater.end() && comp() ) {
sameForBoth(*i_set);
++i_set;
}
}
void sameForBoth() {}
};
Is it possible to refactor methods onFirst and onSecond into one laconic without suffering code maintanability? Note, that compBLess/compBGreater can't be used instead of comp.
My take on the problem:
template<typename TSet>
void onBoth(int val){
TSet* set;
if ( std::is_same<TSet, decltype(m_setLess)>::value ) {
set = reinterpret_cast<TSet*>(&m_setLess);
} else {
set = reinterpret_cast<TSet*>(&m_setGreater);
}
auto i_set = set->begin();
std::function<bool()> comp;
if( std::is_same<TSet, decltype(m_setLess)>::value )
comp = std::function<bool()>([&]() { return val >= i_set->b1; });
else
comp = std::function<bool()>([&]() { return val <= i_set->b1; });
while ( i_set != set->end() && comp() ) {
sameForBoth(*i_set);
++i_set;
}
}
But my solution seems too complex. Also I'm not sure that using reinterpret_cast<> in such manner is a good practice.
Is there any other way?
If I understand this correctly, it seems that you want to apply an action on each element that happens to satisfy the comp unary predicate. Therefore, we may scan the elements linearly and apply a function until a given predicate holds.
Since you are working on a range, a possible approach is to design a generic procedure, as in:
template <typename I, typename P, typename F>
// I models InputIterator
// P models UnaryPredicate
// F models UnaryFunction
// Domain<P> == ValueType<I>
// Domain<F> == ValueType<I>
void apply_until(I first, I last, P p, F f) {
while (first != last) {
if (!p(*first)) return;
f(*first);
++first;
}
}
We can use such a generic algorithm to, e.g., print out the values in a range that happen to be strictly less than 3:
int main() {
std::set<int> s1 = {1, 2, 3, 4, 5};
apply_until(s1.begin(), s1.end(), [](int x) { return x < 3;}, [](int x) { std::cout << x << '\n'; });
}
I would keep the distinction between onFirst and onSecond, as they are meant to operate on distinct sets. The code for your use case may reduce to something like:
void onFirst(int val) {
apply_until(m_setLess.begin(), m_setLess.end(), [&](B const& x) { return x.b1 >= val; }, [&](B const& x) { sameForBoth(x); });
}
void onSecond(int val) {
apply_until(m_setGreater.begin(), m_setGreater.end(), [&](B const& x) { return x.b1 <= val; }, [&](B const& x) { sameForBoth(x); });
}
In both functions, we are iterating over a range, from the beginning of the std::set up-to a given iterator which depends on the input value.
In this answer, I'll assume that compBLess and compBGreater are defined like this (the important part is that the b1 field is predominant over b2. And see at the end for a slightly different version)
struct compBLess {
bool operator ()(B const & o1, B const& o2) const {
return std::make_pair(o1.b1,o1.b2) < std::make_pair(o2.b1,o2.b2);
}
};
struct compBGreater {
bool operator ()(B const & o1, B const& o2) const {
return std::make_pair(o1.b1,o1.b2) > std::make_pair(o2.b1,o2.b2);
}
};
Under this assumption, then I think the idiomatic way to do this is to use lowerbound, upperbound methods of std::set to find the end of the iteration , and then use
template<typename Iterator>
void foo(Iterator it, Iterator end) {
std::for_each(it,end,[this](auto & o){ sameForBoth(o); });
}
This will be performance-wise more efficient, because we will do O(log(size_of_set)) comparisons (using lowerbound / upperbound) instead of O(size_of_set) comparisons (using comp in the loop)
The actual implementation of the other methods looks like this:
void onFirst(int val) {
foo(m_setLess.begin(), m_setLess.lowerbound({val,std::numeric_limits<int>::min}));
}
void onSecond(int val) {
foo(m_setGreater.begin(), m_setGreater.upperbound({val-1,std::numeric_limits<int>::max}));
}
Edit: Following #z3dd's comment, Here is the implementation that works for slightly different compBLess and compBGreater (the ordering vs. the b2 field is reversed):
struct compBLess {
bool operator ()(B const & o1, B const& o2) const {
return std::make_pair(o1.b1,-o1.b2) < std::make_pair(o2.b1,-o2.b2);
}
};
struct compBGreater {
bool operator ()(B const & o1, B const& o2) const {
return std::make_pair(o1.b1,-o1.b2) > std::make_pair(o2.b1,-o2.b2);
}
};
void onFirst(int val) {
foo(m_setLess.begin(), m_setLess.lowerbound({val,std::numeric_limits<int>::max}));
}
void onSecond(int val) {
foo(m_setGreater.begin(), m_setGreater.upperbound({val-1,std::numeric_limits<int>::min}));
}
[Note that if compBLess and compBGreater are not implemented like any of the 2 implementations given, then the answer of #Ilio Catallo is the one to use.]

C++11 for each loop with more than one variable

I would like to translate the following traditional for loop into a C++11 for-each loop without extra looping constructs:
int a[] = { 5, 6, 7, 8, 9, 10 };
int b[] = { 50, 60, 70, 80, 90, 100 };
// Swap a and b array elements
for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
a[i] ^= b[i]; b[i] ^= a[i]; a[i] ^= b[i];
}
Does there exist any way by which it is possible to provide more than one variable in the C++11 for-each loop like:
for (int i, int j : ...)
There is no built-in way to do this. If you can use Boost, boost::combine will work for iterating two (or more) ranges simultaneously (Does boost offer make_zip_range?, How can I iterate over two vectors simultaneously using BOOST_FOREACH?):
for (boost::tuple<int&, int&> ij : boost::combine(a, b)) {
int& i = boost::get<0>(ij);
int& j = boost::get<1>(ij);
// ...
}
Unfortunately accessing the elements within the tuple elements of the zipped range is highly verbose. C++17 will make this much more readable using structured binding:
for (auto [&i, &j] : boost::combine(a, b)) {
// ...
}
Since you don't need to break out of the loop or return from the enclosing function, you could use boost::range::for_each with the body of your loop as a lambda:
boost::range::for_each(a, b, [](int& i, int& j)
{
// ...
});
zip or combine ranges are common in many range libraries.
Writing one strong enough for a for(:) loop isn't hard however.
First we write a basic range type:
template<class It>
struct range_t {
It b,e;
It begin() const{ return b; }
It end() const{ return e; }
range_t without_front( std::size_t count = 1 ) const {
return {std::next(begin()), end()};
}
bool empty() const { return begin()==end(); }
};
template<class It>
range_t<It> range( It b, It e ) { return {b,e}; }
template<class C>
auto range( C& c ) {
using std::begin; using std::end;
return range( begin(c), end(c) );
};
Then we write an iterator that works with ranges (easier than with iterators):
template<class R1, class R2>
struct double_foreach_iterator {
R1 r1;
R2 r2;
void operator++() { r1 = r1.without_front(); r2 = r2.without_front(); }
bool is_end() const { return r1.empty() || r2.empty(); }
auto operator*()const {
return std::tie( *r1.begin(), *r2.begin() );
}
using self=double_foreach_iterator;
auto cur() const {
return std::make_tuple( r1.begin(), r2.begin() );
}
friend bool operator==( self const& lhs, self const& rhs ) {
if (lhs.is_end() || rhs.is_end())
return lhs.is_end() == rhs.is_end();
return lhs.cur() == rhs.cur();
}
friend bool operator!=( self const& lhs, self const& rhs ) {
return !(lhs==rhs);
}
};
now we double iterate:
template<class A, class B>
auto zip_iterate(
A& a, B& b
) {
auto r1 = range(a);
auto r2 = range(b);
auto r1end = range(r1.end(), r1.end());
auto r2end = range(r2.end(), r2.end());
using it = double_foreach_iterator<decltype(r1), decltype(r2)>;
return range( it{r1, r2}, it{r1end, r2end} );
}
which gives us:
for (auto tup : zip_iterate(a, b)) {
int& i = std::get<0>(tup);
int& j = std::get<1>(tup);
// ...
}
or in C++17:
for (auto&& [i, j] : zip_iterate(a, b)) {
// ...
}
My zip iterate does not assume the two containers are of the same length, and will iterate to the length of the shorter one.
live example.
Just for fun.
The following isn't intended to be a serious answer to the question but just an exercise to try to understand the potentiality of C++11 (so, please, be patient).
The following is an example of a class (a draft of a class) that receive a couple of container (with size() method), with the same size (exception otherwise), and of a custom iterator that return a std::pair of std::reference_wrapper to n-position elements.
With a simple use example that show that it's possible to change the value in the starting containers.
Doesn't work with old C-style arrays but works with std::array. We're talking about C++11 so I suppose we could impose the use of std::array.
#include <array>
#include <vector>
#include <iostream>
#include <functional>
template <typename T1, typename T2>
class pairWrapper
{
public:
using V1 = typename std::remove_reference<decltype((T1().at(0)))>::type;
using V2 = typename std::remove_reference<decltype((T2().at(0)))>::type;
using RW1 = std::reference_wrapper<V1>;
using RW2 = std::reference_wrapper<V2>;
class it
{
public:
it (pairWrapper & pw0, std::size_t p0): pos{p0}, pw{pw0}
{ }
it & operator++ ()
{ ++pos; return *this; }
bool operator!= (const it & it0)
{ return pos != it0.pos; }
std::pair<RW1, RW2> & operator* ()
{
static std::pair<RW1, RW2>
p{std::ref(pw.t1[0]), std::ref(pw.t2[0])};
p.first = std::ref(pw.t1[pos]);
p.second = std::ref(pw.t2[pos]);
return p;
}
private:
std::size_t pos;
pairWrapper & pw;
};
it begin()
{ return it(*this, 0U); }
it end()
{ return it(*this, len); }
pairWrapper (T1 & t10, T2 & t20) : len{t10.size()}, t1{t10}, t2{t20}
{ if ( t20.size() != len ) throw std::logic_error("no same len"); }
private:
const std::size_t len;
T1 & t1;
T2 & t2;
};
template <typename T1, typename T2>
pairWrapper<T1, T2> makePairWrapper (T1 & t1, T2 & t2)
{ return pairWrapper<T1, T2>(t1, t2); }
int main()
{
std::vector<int> v1 { 1, 2, 3, 4 };
std::array<long, 4> v2 { { 11L, 22L, 33L, 44L } };
for ( auto & p : makePairWrapper(v1, v2) )
{
std::cout << '{' << p.first << ", " << p.second << '}' << std::endl;
p.first += 3;
p.second += 55;
}
for ( const auto & i : v1 )
std::cout << '[' << i << ']' << std::endl;
for ( const auto & l : v2 )
std::cout << '[' << l << ']' << std::endl;
return 0;
}
p.s.: sorry for my bad English

Elegantly (iterating) parsing data in chunks?

We have some "iterable" collection of data, for instance: std::vector<Foo> bar.
We wish to process Foo elements from bar until some condition is met in which point we "yield" (think Python) the result of all these processed Foos and wait until the next chunk of parsed information is requested.
So far what we're doing is this:
ParsedChunk foobar( std::vector<Foo> bar, size_t* start_from) {
size_t& i = *start_from;
ParsedChunk result_so_far;
for (;i < bar.size(); i++) {
process_some_foo_and_update_chunk(result_so_far, bar[i]);
if (check_condition(? ? ?) {
return result_so_far;
}
}
}
Any suggestions for doing this better?
As I already pointed out in my comment, this is IMO a very good case for an custom iterator:
The iterator scans through your range, as long as some predicate holds, and
when the predicate isn't true for some element, calls a function with the sub range of elements where the predicate held (plus the one that didn't satisfy the predicate). The result of that function call is then the value you get when you dereference the iterator.
template<typename Fn, typename Predicate, typename Iterator>
struct collector {
using value_type = typename std::result_of<Fn(Iterator, Iterator)>::type;
using pointer = value_type const *;
using reference = value_type const &;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
value_type cache;
Fn fn;
Predicate predicate;
Iterator pos, from, stop;
collector(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e)
: fn(std::forward<Fn>(fn)),
predicate(std::forward<Predicate>(p)),
pos(std::forward<Iterator>(s)),
from(pos),
stop(std::forward<Iterator>(e))
{
next_range();
}
collector & operator++(void) {
next_range();
return *this;
}
reference operator*(void) const {
return cache;
}
void next_range(void) {
from = pos;
if (pos == stop) return;
for (; pos != stop; ++pos) {
if (not predicate(*pos)) {
++pos;
break;
}
}
cache = fn(from, pos);
}
collector end_of_range(void) const {
auto copy = collector{*this};
copy.pos = copy.stop;
copy.from = copy.stop;
return copy;
}
bool operator==(collector const & rhs) const {
return (from == rhs.from) and (pos == rhs.pos) and (stop == rhs.stop);
}
bool operator!=(collector const & rhs) const {
return (from != rhs.from) or (pos != rhs.pos) or (stop != rhs.stop);
}
};
template<typename Fn, typename Predicate, typename Iterator>
auto make_collector_range(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e) {
using I = typename std::decay<Iterator>::type;
using P = typename std::decay<Predicate>::type;
using F = typename std::decay<Fn>::type;
using C = collector<F,P,I>;
auto start = C{
std::forward<Fn>(fn), std::forward<Predicate>(p),
std::forward<Iterator>(s), std::forward<Iterator>(e)};
auto stop = start.end_of_range();
return make_pair(std::move(start), std::move(stop));
}
An example usage, calculating the sum of the numbers till 50, but not in one step, but in steps of 15 numbers each:
int main(int, char**) {
vector<int> numbers = vector<int>(50);
generate(begin(numbers), end(numbers),
[i = 0] (void) mutable{
return ++i;
});
copy(begin(numbers), end(numbers), ostream_iterator<int>{cout, " "});
cout << endl;
auto collected = make_collector_range(
[](auto const & from, auto const & to) {
return accumulate(from, to, 0);
},
[](auto const & num) {
return not ((num % 3 == 0) and (num % 5 == 0));
},
begin(numbers), end(numbers));
copy(collected.first, collected.second, ostream_iterator<int>{cout, " "});
cout << endl;
bool passed = accumulate(collected.first, collected.second, 0) == (50*51)/2;
cout << "test " << (passed ? "passed" : "failed") << endl;
return 0;
}
(Live demo here)
(Note: This example uses a fixed "step" width, and predicate and function are unrelated to each other and don't maintain state, but none of this is required by the iterator.)
I hope the intention of the code is clear, if not I can try to provide a more detailed explanation about its workings.