How can you displace the location you iterate through a vector? I've tried something like:
for(auto x : vect+2)
but this doesn't work. I'm sure there's a simple resolve, but I haven't been able to find anything online.
If you want to use the range-based for, you could use Boost.Range to create a range that starts from the third element of your vector (begin() + 2):
for (auto x : boost::make_iterator_range(begin(v) + 2, end(v)))
{
std::cout << x << " ";
}
Here is a simple example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
int main()
{
std::vector<int> v(10);
iota(begin(v), end(v), 1);
for (auto x : boost::make_iterator_range(begin(v) + 2, end(v)))
{
std::cout << x << " ";
}
}
If you want to loop through every second element, instead, you could change your range as follows:
namespace rng = boost::adaptors;
for (auto x : v | rng::strided(2))
{
std::cout << x << " ";
}
Which in a full program would be:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
int main()
{
namespace rng = boost::adaptors;
std::vector<int> v(10);
iota(begin(v), end(v), 1);
for (auto x : v | rng::strided(2))
{
std::cout << x << " ";
}
}
Boost.Range is pretty flexible, so you can for instance combine the two adapters above:
for (auto x : boost::make_iterator_range(begin(v) + 2, end(v)) |
rng::strided(3))
{
std::cout << x << " ";
}
If you do not want or cannot use Boost, you could use a classical for loop with iterators:
for (auto i = begin(v) + 2; i != end(v); ++i)
{
std::cout << *i << " ";
}
This is how the whole program would look like:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v(10);
iota(begin(v), end(v), 1);
for (auto i = begin(v) + 2; i != end(v); ++i)
{
std::cout << *i << " ";
}
}
This can be achieved very simply, and has a number of solutions to suit any programming style.
The Classical Approach
int main()
{
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1);
for (auto i = v.begin() + 2; i != v.end(); ++i)
{
std::cout << *i << " ";
}
}
The Functional Approach
int main()
{
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1);
std::for_each(v.begin() + 2, v.end(), [](int val)
{
std::cout << val << " ";
}
);
}
You could add a light wrapper to make it work with range-based for:
#include <iostream>
#include <vector>
#include <iterator>
namespace range
{
template <typename C>
struct make_range
{
C t;
make_range(C t, int offset)
: t(std::begin(t) + offset, std::end(t))
{}
auto begin() -> decltype(t.begin())
{
return t.begin();
}
auto end() -> decltype(t.end())
{
return t.end();
}
};
}
int main()
{
std::vector<int> v{1, 2, 3, 4, 5};
for (auto i : range::make_range<decltype(v)>(v, 2))
{
std::cout << i << std::endl;
}
}
Perhaps it would be better to just store the iterators:
namespace range
{
template <typename C>
struct make_range
{
typename C::iterator beg_iter;
typename C::iterator end_iter;
make_range(C& t, int offset)
: beg_iter(std::begin(t) + offset), end_iter(std::end(t))
{}
auto begin() -> decltype(beg_iter)
{
return beg_iter;
}
auto end() -> decltype(end_iter)
{
return end_iter;
}
};
}
Related
#include <iostream>
#include <vector>
#include <string>
#include <any>
#include <map>
#include <functional>
#include <exception>
using namespace std;
using MapAny = std::map<string, any>;
int square(int x) {
return x*x;
}
vector<int> parse(map<string, vector<MapAny>> mapping)
{
vector<MapAny> func_square = mapping["square"];
vector<int> res;
for (const auto &mapany : func_square) {
try {
int x = any_cast<int>(mapany.at("x"));
res.push_back(square(x));
}
catch (exception e) {
vector<int> xs = any_cast<vector<int>>(mapany.at("x"));
for (int x : xs) res.push_back(square(x));
}
}
return res;
}
int main()
{
map<string, vector<MapAny>> function_map_value, function_map_array;
function_map_value = {
{"square", { {{"x", 5}}, {{"x", 10}} }}
};
vector<MapAny> vec;
vec.push_back({{"x", vector<int>({5, 10}) }});
function_map_array = {
{"square", vec}
};
vector<int> res1 = parse(function_map_value);
vector<int> res2 = parse(function_map_array);
for (int i=0; i<res1.size(); i++) cout << res1[i] << " "; cout << "\n";
for (int i=0; i<res2.size(); i++) cout << res2[i] << " "; cout << "\n";
return 0;
}
I'm trying to make a function parser that can accept any type, such as both scalar and vector values, like in Python dict().
However, I'm not sure how to check if a std::any object has type std::vector. In the code above, if any_cast fails, it will throw exception and I know it's a std::vector. It's ugly and rely on throwing exception as an expected behavior.
How can I change the above code into something like:
if (is_vector(mapany.at("x")) {
// deal with vector
}
else {
// deal with scalar
}
I have a std::map<std::string, std::vector<std::string>> and I need to perform a threaded task on this map by dividing the map into sub-maps and passing each sub-map to a thread.
With a std::vector<T> I would be able to get a sub-vector pretty easy, by doing this:
#include <vector>
#include <string>
int main(void)
{
size_t off = 0;
size_t num_elms = 100; // Made up value
std::vector<uint8_t> full; // Assume filled with stuff
std::vector<uin8t_t> sub(std::begin(full) + off, std::begin(full) + off + num_elms);
off = off + num_elms;
}
However, doing the same with std::map<T1, T2> gives a compilation error.
#include <vector>
#include <map>
#include <string>
int main(void)
{
size_t off = 0;
size_t num_elms = 100;
std::map<std::string, std::vector<std::string>> full;
std::map<std::string, std::vector<std::string>> sub(std::begin(full) + off,
std::begin(full) + off + num_elms);
off = off + num_elms;
}
It is the same with other std::map "types". Which, from what I have gathered, is down to the iterator.
What is possible is to extract the keys and do something similar to this solution:
#include <map>
#include <vector>
#include <string>
#include <iostream>
void print_map(const std::map<std::string, std::vector<std::string>>& _map)
{
for (const auto& [key, value] : _map)
{
std::cout << "key: " << key << "\nvalues\n";
for (const auto& elm : value)
{
std::cout << "\t" << elm << "\n";
}
}
}
void print_keys(const std::vector<std::string>& keys)
{
std::cout << "keys: \n";
for(const auto& key : keys)
{
std::cout << key << "\n";
}
}
int main(void)
{
std::map<std::string, std::vector<std::string>> full;
full["aa"] = {"aa", "aaaa", "aabb"};
full["bb"] = {"bb", "bbbbb", "bbaa"};
full["cc"] = {"cc", "cccc", "ccbb"};
full["dd"] = {"dd", "dd", "ddcc"};
print_map(full);
std::vector<std::string> keys;
for (const auto& [key, value] : full)
{
(void) value;
keys.emplace_back(key);
}
print_keys(keys);
size_t off = 0;
size_t num_elms = 2;
std::map<std::string, std::vector<std::string>> sub1 (full.find(keys.at(off)), full.find(keys.at(off + num_elms)));
off = off + num_elms;
std::map<std::string, std::vector<std::string>> sub2 (full.find(keys.at(off)), full.find(keys.at(off + num_elms -1)));
std::cout << "sub1:\n";
print_map(sub1);
std::cout << "sub2:\n";
print_map(sub2);
}
However, this has the potential to be extremely inefficient, as the map can be really big (10k+ elements).
So, is there a better way to replicate the std::vector approach with std::map?
A slightly different approach would be to use one of the execution policies added in C++17, like std::execution::parallel_policy. In the example below, the instance std::execution::par is used:
#include <execution>
// ...
std::for_each(std::execution::par, full.begin(), full.end(), [](auto& p) {
// Here you are likely using a thread from a built-in thread pool
auto& vec = p.second;
// do work with "vec"
});
With a slight adaption, you can reasonably easily pass ranges to print_map, and divide up your map by calling std::next on an iterator.
// Minimal range-for support
template <typename Iter>
struct Range {
Range (Iter b, Iter e) : b(b), e(e) {}
Iter b;
Iter e;
Iter begin() const { return b; }
Iter end() const { return e; }
};
// some shorter aliases
using Map = std::map<std::string, std::vector<std::string>>;
using MapView = Range<Map::const_iterator>;
// not necessarily the whole map
void print_map(MapView map) {
for (const auto& [key, value] : map)
{
std::cout << "key: " << key << "\nvalues\n";
for (const auto& elm : value)
{
std::cout << "\t" << elm << "\n";
}
}
}
int main(void)
{
Map full;
full["aa"] = {"aa", "aaaa", "aabb"};
full["bb"] = {"bb", "bbbbb", "bbaa"};
full["cc"] = {"cc", "cccc", "ccbb"};
full["dd"] = {"dd", "dd", "ddcc"};
// can still print the whole map
print_map({ map.begin(), map.end() });
size_t num_elms = 2;
size_t num_full_views = full.size() / num_elms;
std::vector<MapView> views;
auto it = full.begin();
for (size_t i = 0; i < num_full_views; ++i) {
auto next = std::next(it, num_elms);
views.emplace_back(it, next);
it = next;
}
if (it != full.end()) {
views.emplace_back(it, full.end());
}
for (auto view : views) {
print_map(view);
}
}
In C++20 (or with another ranges library), this can be simplified with std::ranges::drop_view / std::ranges::take_view.
using MapView = decltype(std::declval<Map>() | std::ranges::views::drop(0) | std::ranges::views::take(0));
for (size_t i = 0; i < map.size(); i += num_elms) {
views.push_back(map | std::ranges::views::drop(i) | std::ranges::views::take(num_elms));
}
I'm trying to implement the fibonacci sequence in C++17 using for_each
#include <list>
#include <algorithm>
using namespace std;
int main(int argc, char* argv[]) {
list<int> mylist = {1,2,3,4,5};
for_each( next(mylist.begin()), mylist.end(), [](int &n){n = n + prev(n);});
}
to access the previous element inside the function, prev doesn't work. How can I access the previous element inside the function? Thanks.
First, it's much simpler to use std::adjacent_difference for operations on consecutive elements.
If you really want to improve your understanding of std::for_each, then it's possible, but you will have to take responsibility for updating a shadow iterator yourself, as it's not possible to work back from an element to an iterator:
#include <algorithm>
#include <iostream>
#include <list>
int main()
{
std::list<int> v(15);
v.front() = 1;
auto it = v.begin();
auto prev = it;
auto current = *it++;
std::for_each(it, v.end(),
[¤t,&prev](int& n){ std::swap(n, current); current = n+*prev++;});
for (auto n: v) {
std::cout << n << '\n';
}
}
However, if we use std::vector for our storage, then we do have a way to access the previous element, since vectors store their elements contiguously:
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v(15);
v[0] = v[1] = 1;
std::for_each(v.begin()+2, v.end(),
[](int& n){ n = (&n)[-1] + (&n)[-2];});
for (auto n: v) {
std::cout << n << '\n';
}
}
Even if you could use prev to access the previous element, it's unclear how the posted algorithm would generate the expected result (a Fibonacci sequence), because the passed list is initialized as
list<int> mylist = {1, 2, 3, 4, 5};
The lambda would have added (if it worked) the value of the previous element (already modified!) to the current one, resulting in the sequence: 1, 2 + 1 = 3, 3 + 3 = 6, ...
It may be easier to use a stateful lambda and a different algorithm, like std::generate (or std::generate_n).
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <list>
#include <utility>
template <class T>
auto make_fibonacci_generator(T first, T second)
{
return [prev = first, cur = second] () mutable {
return cur += std::exchange(prev, cur);
};
}
template <class OutIt, class T = typename OutIt::value_type>
auto gen_n_fibonacci_numbers(T first, T second, std::size_t n, OutIt dest)
{
if ( n == std::size_t(0) )
return dest;
*dest++ = first;
if ( n == std::size_t(1) )
return dest;
*dest++ = second;
if ( n == std::size_t(2) )
return dest;
return std::generate_n(dest, n - 2, make_fibonacci_generator(first, second));
}
template <class OutIt, class T = typename OutIt::value_type>
void gen_fibonacci_numbers(T first, T second, OutIt dest, OutIt dest_last)
{
if ( dest == dest_last )
return;
*dest++ = first;
if ( dest == dest_last )
return;
*dest++ = second;
if ( dest == dest_last )
return;
std::generate(dest, dest_last, make_fibonacci_generator(first, second));
}
int main()
{
std::list<unsigned int> numbers;
gen_n_fibonacci_numbers(0, 1, 20, std::back_inserter(numbers));
for (auto i : numbers)
std::cout << ' ' << i;
std::cout << '\n';
std::array<int, 10> nums;
gen_fibonacci_numbers(0, 1, nums.begin(), nums.end());
for (auto i : nums)
std::cout << ' ' << i;
std::cout << '\n';
}
Testable here.
I would like to do something like this:
for (int p : colourPos[i+1])
How do I skip the first iteration of my colourPos vector?
Can I use .begin() and .end()?
Since C++20 you can use the range adaptor std::views::drop from the Ranges library together with a range-based for loop for skipping the first element, as follows:
std::vector<int> colourPos { 1, 2, 3 };
for (int p : colourPos | std::views::drop(1)) {
std::cout << "Pos = " << p << std::endl;
}
Output:
Pos = 2
Pos = 3
Code on Wandbox
Note: I would not recommend using a solution that contains begin() and/or end(), because the idea of a range-based for loop is to get rid of iterators. If you need iterators, then I would stick with an interator-based for loop.
Live demo link.
#include <iostream>
#include <vector>
#include <iterator>
#include <cstddef>
template <typename T>
struct skip
{
T& t;
std::size_t n;
skip(T& v, std::size_t s) : t(v), n(s) {}
auto begin() -> decltype(std::begin(t))
{
return std::next(std::begin(t), n);
}
auto end() -> decltype(std::end(t))
{
return std::end(t);
}
};
int main()
{
std::vector<int> v{ 1, 2, 3, 4 };
for (auto p : skip<decltype(v)>(v, 1))
{
std::cout << p << " ";
}
}
Output:
2 3 4
Or simpler:
Yet another live demo link.
#include <iostream>
#include <vector>
template <typename T>
struct range_t
{
T b, e;
range_t(T x, T y) : b(x), e(y) {}
T begin()
{
return b;
}
T end()
{
return e;
}
};
template <typename T>
range_t<T> range(T b, T e)
{
return range_t<T>(b, e);
}
int main()
{
std::vector<int> v{ 1, 2, 3, 4 };
for (auto p : range(v.begin()+1, v.end()))
{
std::cout << p << " ";
}
}
Output:
2 3 4
Do this:
bool first = true;
for (int p : colourPos)
{
if (first)
{ first = false; continue; }
// ...
}
I've been playing with C++11 functional in order to do the same as python's itertools.combinations(input, 2), so far this is what I have:
EDIT removed outer lambda as suggested by #DavidRodrÃguez-dribeas
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
template <class T>
function<pair<T*, T*>()> combinations(vector<T> & input) {
auto it1 = input.begin();
auto end = input.end();
auto it2 = next(it1);
return [=]() mutable {
if (it2 == end) {
it1++;
it2 = next(it1);
}
if (it2 != end)
return pair<T*,T*>(&(*it1), &(*it2++));
return pair<T*,T*>(&*end, &*end);
};
};
int main (void) {
vector<int> numbers{1,2,3,4,5,6};
auto func = combinations(numbers);
while ( true ) {
auto i = func();
if (i.first == &*(numbers.end())) break;
cout << *(i.first) << ',' << *(i.second) << endl;
}
return 0;
};
I'm not happy with the method used to iterate over the combinations any advice on cleaning it up?
Here is documentation and code on my favorite way of doing this. And here is how that library would be used for your example:
#include <iostream>
#include <vector>
#include "combinations"
using namespace std;
int main (void) {
vector<int> numbers{1,2,3,4,5,6};
for_each_combination(numbers.begin(), numbers.begin()+2, numbers.end(),
[](vector<int>::const_iterator b, vector<int>::const_iterator e)
{
if (b != e)
{
cout << *b;
for (auto i = b+1; i != e; ++i)
cout << ',' << *i;
cout << endl;
}
return false;
});
}
1,2
1,3
1,4
1,5
1,6
2,3
2,4
2,5
2,6
3,4
3,5
3,6
4,5
4,6
5,6
Should the need arise, it is trivial to change the example use to consider 3 or 4 items at time instead of 2. One can also deal with various permutations k out of N at a time.
Update
Adding a level of indirection to illustrate how you would deal with a vector of items that were not efficient at moving/swapping around in the vector:
#include <iostream>
#include <vector>
#include "combinations"
using namespace std;
int main (void) {
vector<int> numbers{1,2,3,4,5,6};
vector<vector<int>::const_iterator> num_iters;
num_iters.reserve(numbers.size());
for (auto i = numbers.begin(); i != numbers.end(); ++i)
num_iters.push_back(i);
for_each_combination(num_iters.begin(), num_iters.begin()+2, num_iters.end(),
[](vector<vector<int>::const_iterator>::const_iterator b,
vector<vector<int>::const_iterator>::const_iterator e)
{
if (b != e)
{
cout << **b;
for (auto i = b+1; i != e; ++i)
cout << ',' << **i;
cout << endl;
}
return false;
});
}
I found out that Oliver Kowalke's coroutine library has been accepted by Boosts peer review and should be included hopefully in the next version. Jumping the gun a bit I gave it a go by using the coroutine branch of the boost-dev repo (https://gitorious.org/boost-dev/boost-dev).
g++ -I path/to/boost-dev -std=c++11 test_code.cpp -o run_test_code -static -L path/to/boost-dev/stage/lib/ -lboost_context
#include <boost/coroutine/all.hpp>
#include <boost/bind.hpp>
#include <boost/range.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace boost;
template <typename T>
using coro_pairT_void = coroutines::coroutine<pair<T&,T&>(void)>;
template <typename T>
void combinations(typename coro_pairT_void<T>::caller_type & self, vector<T> & input ) {
for (auto it1 = input.begin(), itend = input.end(); it1 != itend; it1++) {
for (auto it2 = std::next(it1); it2 != itend; it2++) {
self(pair<T&, T&>(*it1,*it2));
}
}
};
int main( void ) {
vector<int> numbers{1,2,3,4,5,6};
coro_pairT_void<int> func(bind(combinations<int>, _1, numbers));
for (auto it(begin(func)), itend(end(func)); it != itend; ++it) {
cout << it->first << ',' << it->second << endl;
}
return 0;
};