Indices vs iterators [duplicate] - c++

C++11 provides multiple ways to iterate over containers. For example:
Range-based loop
for(auto c : container) fun(c)
std::for_each
for_each(container.begin(),container.end(),fun)
However what is the recommended way to iterate over two (or more) containers of the same size to accomplish something like:
for(unsigned i = 0; i < containerA.size(); ++i) {
containerA[i] = containerB[i];
}

Rather late to the party. But: I would iterate over indices. But not with the classical for loop but instead with a range-based for loop over the indices:
for(unsigned i : indices(containerA)) {
containerA[i] = containerB[i];
}
indices is a simple wrapper function which returns a (lazily evaluated) range for the indices. Since the implementation – though simple – is a bit too long to post it here, you can find an implementation on GitHub.
This code is as efficient as using a manual, classical for loop.
If this pattern occurs often in your data, consider using another pattern which zips two sequences and produces a range of tuples, corresponding to the paired elements:
for (auto& [a, b] : zip(containerA, containerB)) {
a = b;
}
The implementation of zip is left as an exercise for the reader, but it follows easily from the implementation of indices.
(Before C++17 you’d have to write the following instead:)
for (auto&& items : zip(containerA, containerB))
get<0>(items) = get<1>(items);

i wonder why no one mentioned this:
auto itA = vectorA.begin();
auto itB = vectorB.begin();
while(itA != vectorA.end() || itB != vectorB.end())
{
if(itA != vectorA.end())
{
++itA;
}
if(itB != vectorB.end())
{
++itB;
}
}
PS: if the container sizes don't match, then you may need to put each container specific code into its corresponding if block.

For your specific example, just use
std::copy_n(contB.begin(), contA.size(), contA.begin())
For the more general case, you can use Boost.Iterator's zip_iterator, with a small function to make it usable in range-based for loops. For most cases, this will work:
template<class... Conts>
auto zip_range(Conts&... conts)
-> decltype(boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))))
{
return {boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))};
}
// ...
for(auto&& t : zip_range(contA, contB))
std::cout << t.get<0>() << " : " << t.get<1>() << "\n";
Live example.
However, for full-blown genericity, you probably want something more like this, which will work correctly for arrays and user-defined types that don't have member begin()/end() but do have begin/end functions in their namespace. Also, this will allow the user to specifically get const access through the zip_c... functions.
And if you're an advocate of nice error messages, like me, then you probably want this, which checks if any temporary containers were passed to any of the zip_... functions, and prints a nice error message if so.

There are a lot of ways to do specific things with multiple containers as provided in the algorithm header. For instance, in the example you've given, you could use std::copy instead of an explicit for loop.
On the other hand, there isn't any built-in way to generically iterate multiple containers other than a normal for loop. This isn't surprising because there are a lot of ways to iterate. Think about it: you could iterate through one container with one step, one container with another step; or through one container until it gets to the end then start inserting while you go through to the end of the other container; or one step of the first container for every time you completely go through the other container then start over; or some other pattern; or more than two containers at a time; etc ...
However, if you wanted to make your own "for_each" style function that iterates through two containers only up to the length of the shortest one, you could do something like this:
template <typename Container1, typename Container2>
void custom_for_each(
Container1 &c1,
Container2 &c2,
std::function<void(Container1::iterator &it1, Container2::iterator &it2)> f)
{
Container1::iterator begin1 = c1.begin();
Container2::iterator begin2 = c2.begin();
Container1::iterator end1 = c1.end();
Container2::iterator end2 = c2.end();
Container1::iterator i1;
Container2::iterator i2;
for (i1 = begin1, i2 = begin2; (i1 != end1) && (i2 != end2); ++it1, ++i2) {
f(i1, i2);
}
}
Obviously you can make any kind of iterations strategy you want in a similar way.
Of course, you might argue that just doing the inner for loop directly is easier than writing a custom function like this ... and you'd be right, if you are only going to do it one or two times. But the nice thing is that this is very reusable. =)

In case when you need to iterate simultaneously over 2 containers only, there is an extended version of standard for_each algorithm in boost range library, e.g:
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/bind.hpp>
#include <boost/range/algorithm_ext/for_each.hpp>
void foo(int a, int& b)
{
b = a + 1;
}
int main()
{
std::vector<int> contA = boost::assign::list_of(4)(3)(5)(2);
std::vector<int> contB(contA.size(), 0);
boost::for_each(contA, contB, boost::bind(&foo, _1, _2));
// contB will be now 5,4,6,3
//...
return 0;
}
When you need to handle more than 2 containers in one algorithm, then you need to play with zip.

another solution could be capturing a reference of the iterator of the other container in a lambda and using post increment operator on that. for example simple copy would be:
vector<double> a{1, 2, 3};
vector<double> b(3);
auto ita = a.begin();
for_each(b.begin(), b.end(), [&ita](auto &itb) { itb = *ita++; })
inside lambda you can do whatever with ita and then increment it. This easily extends to the multiple containers case.

A range-library provides this and other very helpful functionality. The following example uses Boost.Range. Eric Niebler's rangev3 should be a good alternative.
#include <boost/range/combine.hpp>
#include <iostream>
#include <vector>
#include <list>
int main(int, const char*[])
{
std::vector<int> const v{0,1,2,3,4};
std::list<char> const l{'a', 'b', 'c', 'd', 'e'};
for(auto const& i: boost::combine(v, l))
{
int ti;
char tc;
boost::tie(ti,tc) = i;
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}
C++17 will make this even better with structured bindings:
int main(int, const char*[])
{
std::vector<int> const v{0,1,2,3,4};
std::list<char> const l{'a', 'b', 'c', 'd', 'e'};
for(auto const& [ti, tc]: boost::combine(v, l))
{
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}

I'm a bit late too; but you can use this (C-style variadic function):
template<typename T>
void foreach(std::function<void(T)> callback, int count, ...) {
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
std::vector<T> v = va_arg(args, std::vector<T>);
std::for_each(v.begin(), v.end(), callback);
}
va_end(args);
}
foreach<int>([](const int &i) {
// do something here
}, 6, vecA, vecB, vecC, vecD, vecE, vecF);
or this (using a function parameter pack):
template<typename Func, typename T>
void foreach(Func callback, std::vector<T> &v) {
std::for_each(v.begin(), v.end(), callback);
}
template<typename Func, typename T, typename... Args>
void foreach(Func callback, std::vector<T> &v, Args... args) {
std::for_each(v.begin(), v.end(), callback);
return foreach(callback, args...);
}
foreach([](const int &i){
// do something here
}, vecA, vecB, vecC, vecD, vecE, vecF);
or this (using a brace-enclosed initializer list):
template<typename Func, typename T>
void foreach(Func callback, std::initializer_list<std::vector<T>> list) {
for (auto &vec : list) {
std::for_each(vec.begin(), vec.end(), callback);
}
}
foreach([](const int &i){
// do something here
}, {vecA, vecB, vecC, vecD, vecE, vecF});
or you can join vectors like here: What is the best way to concatenate two vectors? and then iterate over big vector.

I personally prefer using what is already in the STL (in the <algorithm> header) if possible. std::transform has a signature that can take two input iterators. So at least for the case of two input containers you could do:
std::transform(containerA.begin(), containerA.end(), containerB.begin(), outputContainer.begin(), [&](const auto& first, const auto& second){
return do_operation(first, second);
});
Note that the outputContainer can also be one of the input containers. But one limitation is that you cannot do a post update operation if you are modifying one of the containers in place.

The answer is here!... when C++23 comes.
#include <algorithm>
#include <forward_list>
#include <ranges>
#include <array>
#include <iostream>
int main()
{
auto foos = std::to_array({ 1, 2, 3, 4, 5 });
auto woos = std::to_array({ 6, 7, 8, 9, 10 });
auto fooswoos = std::views::zip(foos,woos);
for(auto [foo, woo] : fooswoos) {
woo += foo;
}
std::ranges::for_each(woos, [](const auto& e) { std::cout << e << '\n'; });
return 0;
}
So, what's happening?
We are constructing a special "view". This view allows us to look at containers as if they were other structures without actually doing any copying or anything like that. Using a structured binding we are able to take a reference to each aligning element per iteration and do whatever we want to it (and safely)
Check it out on compiler explorer right now!

Here is one variant
template<class ... Iterator>
void increment_dummy(Iterator ... i)
{}
template<class Function,class ... Iterator>
void for_each_combined(size_t N,Function&& fun,Iterator... iter)
{
while(N!=0)
{
fun(*iter...);
increment_dummy(++iter...);
--N;
}
}
Example usage
void arrays_mix(size_t N,const float* x,const float* y,float* z)
{
for_each_combined(N,[](float x,float y,float& z){z=x+y;},x,y,z);
}

Related

`c++17` ranged for loop over std::vectors with value and index [duplicate]

Is there an equivalent to the range-based enumerate loop from python in C++?
I would imagine something like this.
enumerateLoop (auto counter, auto el, container) {
charges.at(counter) = el[0];
aa.at(counter) = el[1];
}
Can this be done with templates or macros?
I'm aware that I can just use an old school for-loop and iterate until I reach container.size(). But I'm interested how this would be solved using templates or macros.
EDIT
I played a bit with boost iterators after the hint in the comments. I got another working solution using C++14.
template <typename... T>
auto zip(const T &... containers) -> boost::iterator_range<boost::zip_iterator<
decltype(boost::make_tuple(std::begin(containers)...))>> {
auto zip_begin =
boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...));
auto zip_end =
boost::make_zip_iterator(boost::make_tuple(std::end(containers)...));
return boost::make_iterator_range(zip_begin, zip_end);
}
template <typename T>
auto enumerate(const T &container) {
return zip(boost::counting_range(0, static_cast<int>(container.size())),
container);
}
https://gist.github.com/kain88-de/fef962dc1c15437457a8
Enumeration of multiple variables has been an idiom since C. The only complication is that you can't declare both variables in the initializer of the for loop.
int index;
for (auto p = container.begin(), index = 0; p != container.end(); ++p, ++index)
I don't think it gets any simpler (or more powerful) than that.
There is a pre C++11 solution in boost to this: boost.range.indexed.
Unfortunately it doesn't work with C++11 range based for-loops, only old style verbose loops. However with C++17 it should be become (almost) as easy as in python using structured bindings
Then it should be possible implement something that works like this:
for (auto& [n,x] : enumerate(vec)) x = n;
So, a bit of waiting still ;)
I wrote something for this a while back.
Essentially, you need to wrap an iterator and give it pair semantics.
AFAIK, there's nothing like this built into the language. And I don't think boost has it either. You pretty much have to roll your own.
// Wraps a forward-iterator to produce {value, index} pairs, similar to
// python's enumerate()
template <typename Iterator>
struct EnumerateIterator {
private:
Iterator current;
Iterator last;
size_t index;
bool atEnd;
public:
typedef decltype(*std::declval<Iterator>()) IteratorValue;
typedef pair<IteratorValue const&, size_t> value_type;
EnumerateIterator()
: index(0), atEnd(true) {}
EnumerateIterator(Iterator begin, Iterator end)
: current(begin), last(end), index(0) {
atEnd = current == last;
}
EnumerateIterator begin() const {
return *this;
}
EnumerateIterator end() const {
return EnumerateIterator();
}
EnumerateIterator operator++() {
if (!atEnd) {
++current;
++index;
atEnd = current == last;
}
return *this;
}
value_type operator*() const {
return {*current, index};
}
bool operator==(EnumerateIterator const& rhs) const {
return
(atEnd && rhs.atEnd) ||
(!atEnd && !rhs.atEnd && current == rhs.current && last == rhs.last);
}
bool operator!=(EnumerateIterator const& rhs) const {
return !(*this == rhs);
}
explicit operator bool() const {
return !atEnd;
}
};
template<typename Iterable>
EnumerateIterator<decltype(std::declval<Iterable>().begin())> enumerateIterator(Iterable& list) {
return EnumerateIterator<decltype(std::declval<Iterable>().begin())>(list.begin(), list.end());
}
template<typename ResultContainer, typename Iterable>
ResultContainer enumerateConstruct(Iterable&& list) {
ResultContainer res;
for (auto el : enumerateIterator(list))
res.push_back(move(el));
return res;
}
C++17 and structured bindings makes this look OK - certainly better than some ugly mutable lambda with a local [i = 0](Element&) mutable or whatever I've done before admitting that probably not everything should be shoehorned into for_each() et al. - and than other solutions that require a counter with scope outside the for loop.
for (auto [it, end, i] = std::tuple{container.cbegin(), container.cend(), 0};
it != end; ++it, ++i)
{
// something that needs both `it` and `i`ndex
}
You could make this generic, if you use this pattern often enough:
template <typename Container>
auto
its_and_idx(Container&& container)
{
using std::begin, std::end;
return std::tuple{begin(container), end(container), 0};
}
// ...
for (auto [it, end, i] = its_and_idx(foo); it != end; ++it, ++i)
{
// something
}
C++ Standard proposal P2164 proposes to add views::enumerate, which would provide a view of a range giving both reference-to-element and index-of-element to a user iterating it.
We propose a view enumerate whose value type is a struct with 2 members index and value representing respectively the position and value of the elements in the adapted range.
[ . . .]
This feature exists in some form in Python, Rust, Go (backed into the language), and in many C++ libraries: ranges-v3, folly, boost::ranges (indexed).
The existence of this feature or lack thereof is the subject of recurring stackoverflow questions.
Hey, look! We're famous.
You can also more elegantly use the auto ranges available since C++11:
int i = 0;
for (auto& el : container){
charges.at(counter) = el[0];
aa.at(counter) = el[1];
++i;
}
You still have to count the i up by hand, though.
Here's a macro-based solution that probably beats most others on simplicity, compile time, and code generation quality:
#include <iostream>
#define fori(i, ...) if(size_t i = -1) for(__VA_ARGS__) if(i++, true)
int main() {
fori(i, auto const & x : {"hello", "world", "!"}) {
std::cout << i << " " << x << std::endl;
}
}
Result:
$ g++ -o enumerate enumerate.cpp -std=c++11 && ./enumerate
0 hello
1 world
2 !
Tobias Widlund wrote a nice MIT licensed Python style header only enumerate (C++17 though):
GitHub
Blog Post
Really nice to use:
std::vector<int> my_vector {1,3,3,7};
for(auto [i, my_element] : en::enumerate(my_vector))
{
// do stuff
}
Boost::Range supports this as of 1.56.
#include <boost/range/adaptor/indexed.hpp>
#include <boost/assign.hpp>
#include <iterator>
#include <iostream>
#include <vector>
int main(int argc, const char* argv[])
{
using namespace boost::assign;
using namespace boost::adaptors;
std::vector<int> input;
input += 10,20,30,40,50,60,70,80,90;
// for (const auto& element : index(input, 0)) // function version
for (const auto& element : input | indexed(0))
{
std::cout << "Element = " << element.value()
<< " Index = " << element.index()
<< std::endl;
}
return 0;
}

What is the best and most efficient way to traverse 2 vectors at the same time? [duplicate]

C++11 provides multiple ways to iterate over containers. For example:
Range-based loop
for(auto c : container) fun(c)
std::for_each
for_each(container.begin(),container.end(),fun)
However what is the recommended way to iterate over two (or more) containers of the same size to accomplish something like:
for(unsigned i = 0; i < containerA.size(); ++i) {
containerA[i] = containerB[i];
}
Rather late to the party. But: I would iterate over indices. But not with the classical for loop but instead with a range-based for loop over the indices:
for(unsigned i : indices(containerA)) {
containerA[i] = containerB[i];
}
indices is a simple wrapper function which returns a (lazily evaluated) range for the indices. Since the implementation – though simple – is a bit too long to post it here, you can find an implementation on GitHub.
This code is as efficient as using a manual, classical for loop.
If this pattern occurs often in your data, consider using another pattern which zips two sequences and produces a range of tuples, corresponding to the paired elements:
for (auto& [a, b] : zip(containerA, containerB)) {
a = b;
}
The implementation of zip is left as an exercise for the reader, but it follows easily from the implementation of indices.
(Before C++17 you’d have to write the following instead:)
for (auto&& items : zip(containerA, containerB))
get<0>(items) = get<1>(items);
i wonder why no one mentioned this:
auto itA = vectorA.begin();
auto itB = vectorB.begin();
while(itA != vectorA.end() || itB != vectorB.end())
{
if(itA != vectorA.end())
{
++itA;
}
if(itB != vectorB.end())
{
++itB;
}
}
PS: if the container sizes don't match, then you may need to put each container specific code into its corresponding if block.
For your specific example, just use
std::copy_n(contB.begin(), contA.size(), contA.begin())
For the more general case, you can use Boost.Iterator's zip_iterator, with a small function to make it usable in range-based for loops. For most cases, this will work:
template<class... Conts>
auto zip_range(Conts&... conts)
-> decltype(boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))))
{
return {boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))};
}
// ...
for(auto&& t : zip_range(contA, contB))
std::cout << t.get<0>() << " : " << t.get<1>() << "\n";
Live example.
However, for full-blown genericity, you probably want something more like this, which will work correctly for arrays and user-defined types that don't have member begin()/end() but do have begin/end functions in their namespace. Also, this will allow the user to specifically get const access through the zip_c... functions.
And if you're an advocate of nice error messages, like me, then you probably want this, which checks if any temporary containers were passed to any of the zip_... functions, and prints a nice error message if so.
There are a lot of ways to do specific things with multiple containers as provided in the algorithm header. For instance, in the example you've given, you could use std::copy instead of an explicit for loop.
On the other hand, there isn't any built-in way to generically iterate multiple containers other than a normal for loop. This isn't surprising because there are a lot of ways to iterate. Think about it: you could iterate through one container with one step, one container with another step; or through one container until it gets to the end then start inserting while you go through to the end of the other container; or one step of the first container for every time you completely go through the other container then start over; or some other pattern; or more than two containers at a time; etc ...
However, if you wanted to make your own "for_each" style function that iterates through two containers only up to the length of the shortest one, you could do something like this:
template <typename Container1, typename Container2>
void custom_for_each(
Container1 &c1,
Container2 &c2,
std::function<void(Container1::iterator &it1, Container2::iterator &it2)> f)
{
Container1::iterator begin1 = c1.begin();
Container2::iterator begin2 = c2.begin();
Container1::iterator end1 = c1.end();
Container2::iterator end2 = c2.end();
Container1::iterator i1;
Container2::iterator i2;
for (i1 = begin1, i2 = begin2; (i1 != end1) && (i2 != end2); ++it1, ++i2) {
f(i1, i2);
}
}
Obviously you can make any kind of iterations strategy you want in a similar way.
Of course, you might argue that just doing the inner for loop directly is easier than writing a custom function like this ... and you'd be right, if you are only going to do it one or two times. But the nice thing is that this is very reusable. =)
In case when you need to iterate simultaneously over 2 containers only, there is an extended version of standard for_each algorithm in boost range library, e.g:
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/bind.hpp>
#include <boost/range/algorithm_ext/for_each.hpp>
void foo(int a, int& b)
{
b = a + 1;
}
int main()
{
std::vector<int> contA = boost::assign::list_of(4)(3)(5)(2);
std::vector<int> contB(contA.size(), 0);
boost::for_each(contA, contB, boost::bind(&foo, _1, _2));
// contB will be now 5,4,6,3
//...
return 0;
}
When you need to handle more than 2 containers in one algorithm, then you need to play with zip.
another solution could be capturing a reference of the iterator of the other container in a lambda and using post increment operator on that. for example simple copy would be:
vector<double> a{1, 2, 3};
vector<double> b(3);
auto ita = a.begin();
for_each(b.begin(), b.end(), [&ita](auto &itb) { itb = *ita++; })
inside lambda you can do whatever with ita and then increment it. This easily extends to the multiple containers case.
A range-library provides this and other very helpful functionality. The following example uses Boost.Range. Eric Niebler's rangev3 should be a good alternative.
#include <boost/range/combine.hpp>
#include <iostream>
#include <vector>
#include <list>
int main(int, const char*[])
{
std::vector<int> const v{0,1,2,3,4};
std::list<char> const l{'a', 'b', 'c', 'd', 'e'};
for(auto const& i: boost::combine(v, l))
{
int ti;
char tc;
boost::tie(ti,tc) = i;
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}
C++17 will make this even better with structured bindings:
int main(int, const char*[])
{
std::vector<int> const v{0,1,2,3,4};
std::list<char> const l{'a', 'b', 'c', 'd', 'e'};
for(auto const& [ti, tc]: boost::combine(v, l))
{
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}
I'm a bit late too; but you can use this (C-style variadic function):
template<typename T>
void foreach(std::function<void(T)> callback, int count, ...) {
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
std::vector<T> v = va_arg(args, std::vector<T>);
std::for_each(v.begin(), v.end(), callback);
}
va_end(args);
}
foreach<int>([](const int &i) {
// do something here
}, 6, vecA, vecB, vecC, vecD, vecE, vecF);
or this (using a function parameter pack):
template<typename Func, typename T>
void foreach(Func callback, std::vector<T> &v) {
std::for_each(v.begin(), v.end(), callback);
}
template<typename Func, typename T, typename... Args>
void foreach(Func callback, std::vector<T> &v, Args... args) {
std::for_each(v.begin(), v.end(), callback);
return foreach(callback, args...);
}
foreach([](const int &i){
// do something here
}, vecA, vecB, vecC, vecD, vecE, vecF);
or this (using a brace-enclosed initializer list):
template<typename Func, typename T>
void foreach(Func callback, std::initializer_list<std::vector<T>> list) {
for (auto &vec : list) {
std::for_each(vec.begin(), vec.end(), callback);
}
}
foreach([](const int &i){
// do something here
}, {vecA, vecB, vecC, vecD, vecE, vecF});
or you can join vectors like here: What is the best way to concatenate two vectors? and then iterate over big vector.
I personally prefer using what is already in the STL (in the <algorithm> header) if possible. std::transform has a signature that can take two input iterators. So at least for the case of two input containers you could do:
std::transform(containerA.begin(), containerA.end(), containerB.begin(), outputContainer.begin(), [&](const auto& first, const auto& second){
return do_operation(first, second);
});
Note that the outputContainer can also be one of the input containers. But one limitation is that you cannot do a post update operation if you are modifying one of the containers in place.
The answer is here!... when C++23 comes.
#include <algorithm>
#include <forward_list>
#include <ranges>
#include <array>
#include <iostream>
int main()
{
auto foos = std::to_array({ 1, 2, 3, 4, 5 });
auto woos = std::to_array({ 6, 7, 8, 9, 10 });
auto fooswoos = std::views::zip(foos,woos);
for(auto [foo, woo] : fooswoos) {
woo += foo;
}
std::ranges::for_each(woos, [](const auto& e) { std::cout << e << '\n'; });
return 0;
}
So, what's happening?
We are constructing a special "view". This view allows us to look at containers as if they were other structures without actually doing any copying or anything like that. Using a structured binding we are able to take a reference to each aligning element per iteration and do whatever we want to it (and safely)
Check it out on compiler explorer right now!
Here is one variant
template<class ... Iterator>
void increment_dummy(Iterator ... i)
{}
template<class Function,class ... Iterator>
void for_each_combined(size_t N,Function&& fun,Iterator... iter)
{
while(N!=0)
{
fun(*iter...);
increment_dummy(++iter...);
--N;
}
}
Example usage
void arrays_mix(size_t N,const float* x,const float* y,float* z)
{
for_each_combined(N,[](float x,float y,float& z){z=x+y;},x,y,z);
}

How to find duplicates in a std::vector<strings> and return a std::list of them sorted alphabetically without duplicates in that resulting list

I have a class called Wordd, that has a member word_ which is a std::list
I am trying to find duplicates in that word_, and return an alphabetized list of them without duplicates in that returned list. So far my code compiles and links, but times out, probably due to some internal memory leakage, etc.
class FindDuplicatesFunctor
{
public:
std::list<std::string> list;
std::vector<std::string> word_;
FindDuplicatesFunctor(std::vector<std::string> words): list(0), word_(words){};
void operator()(std::string const& str)
{
if(std::count(words_.begin(), words_.end(), str) > 1 && std::count(list.begin(), list.end(), str) == 0)
{
list.push_back(str);
}
list.sort();
}
};
std::list<string> Wordd::FindDuplicates() const
{
FindDuplicatesFunctor cf(word_);
return std::for_each(words_.begin(), words_.end(), cf).list;
}
Any ideas why it's not performing its tasks?
Thank you in advance for your help!
Edit In response to comment:
Remove duplicates function name is misleading, it is actually trying to return a list of words that are repeating in the sequence, but that result list only has one copy of each duplicate – user2624236 10 hours ago
I hinted std::sort + std::adjacent_find(... std::equal_to<>). Here's the realization of that:
template <typename C, typename T = typename C::value_type> std::list<T> adjacent_search(C input)
{
std::sort(begin(input), end(input));
static const auto eq = std::equal_to<T>{};
static const auto neq= std::not2(eq);
std::list<T> dupes;
auto end_streak = begin(input);
auto dupe_at = std::adjacent_find(end_streak, end(input), eq);
for(auto end_streak=begin(input);
(dupe_at = std::adjacent_find(end_streak, end(input), eq)) != end(input);
end_streak = std::adjacent_find(dupe_at, end(input), neq))
{
dupes.insert(dupes.end(), *dupe_at);
}
return dupes;
}
This implementation has several nice properties, such as a linear scan and reasonable worst case behaviour (e.g. if input contains 1000 duplicates of a single value, it won't do 1001 useless searches).
However, the following (using a set) might be a lot simpler:
// simple, but horrific performance
template <typename C, typename T = typename C::value_type> std::list<T> simple(C const& input)
{
std::set<T> dupes; // optimization, dupes.find(x) in O(log n)
for (auto it = begin(input); it != end(input); ++it)
{
if ((end(dupes) == dupes.find(*it))) // optimize by reducing find() calls
&& (std::count(it, end(input), *it) > 1))
{
dupes.insert(dupes.end(), *it);
}
}
return {begin(dupes), end(dupes)};
}
This will almost certainly perform better on smaller collections because there is less copying (except for the result). It could get rather bad worst case behaviour (for large inputs) because of the implicit linear search in std::count.
I'd suggest you return the std::set<T> directly, instead of copying it to the list.
Here's a test running Live on Coliru showing both versions.
Original answer
Now rather obsolete, because it didn't do what the OP wanted:
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<std::string> input = { "unsorted", "containing", "optional", "unsorted", "duplicate", "duplicate", "values" };
std::sort(begin(input), end(input));
std::unique_copy(begin(input), end(input), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << "\n";
}
Output:
containing duplicate optional unsorted values
See it live: http://coliru.stacked-crooked.com/view?id=f8cc78dbcce62ad276691b6541629a70-542192d2d8aca3c820c7acc656fa0c68
sort-unique-erase:
template<typename Container>
Container&& sort_unique_erase( Container&& c ) {
using std::begin; using std::end;
std::sort( begin(c), end(c) );
c.erase( std::unique( begin(c), end(c) ), end(c) );
return std::forward<Container>(c);
}
works on any random access container that you can erase ranges from (vector and deque in namespace std).
Append then:
template<typename C1, typename C2>
C1&& append( C1&& c1, C2&& c2 ) {
using std::begin; using std::end;
c1.insert( end(c1), std::make_move_iterator( begin(c2) ), std::make_move_iterator( end(c2) ) );
return std::forward<C1>(c1);
}
template<typename C1, typename C2>
C1&& append( C1&& c1, C2& c2 ) {
using std::begin; using std::end;
c1.insert( end(c1), begin(c2), end(c2) );
return std::forward<C1>(c1);
}
and tie them together:
int main() {
std::vector<std::string> words = {"hello", "world", "my", "name", "is", "hello"};
std::list<std::string> retval;
append( retval, sort_unique_erase( std::move(words) ) );
for( auto& str : retval ) {
std::cout << str << "\n";
}
}
however, using std::list is not advised: there are very few reasons to use it over std::vector, or in some rare cases std::deque.
The FindDuplicates() function references word_ and words_. It seems, these two names are meant to be the same, which one it should be, can't be determined from the code snippet.
The used algorithm is hideously slow, however: it requires O(n * n) time, potentially using many list operations which are even slower than vector operations. You surely want to use an approach along the lines of what sehe has posted (std::sort() followed by std::unique_copy()). If your set of values is really huge, you might want to consider to move to the set just once and keep a std::set<std::string> (or std::unordered_set<std::string>) or a a version using a std::string const* to determine if the value was already seen.

What's the best way to iterate over two or more containers simultaneously

C++11 provides multiple ways to iterate over containers. For example:
Range-based loop
for(auto c : container) fun(c)
std::for_each
for_each(container.begin(),container.end(),fun)
However what is the recommended way to iterate over two (or more) containers of the same size to accomplish something like:
for(unsigned i = 0; i < containerA.size(); ++i) {
containerA[i] = containerB[i];
}
Rather late to the party. But: I would iterate over indices. But not with the classical for loop but instead with a range-based for loop over the indices:
for(unsigned i : indices(containerA)) {
containerA[i] = containerB[i];
}
indices is a simple wrapper function which returns a (lazily evaluated) range for the indices. Since the implementation – though simple – is a bit too long to post it here, you can find an implementation on GitHub.
This code is as efficient as using a manual, classical for loop.
If this pattern occurs often in your data, consider using another pattern which zips two sequences and produces a range of tuples, corresponding to the paired elements:
for (auto& [a, b] : zip(containerA, containerB)) {
a = b;
}
The implementation of zip is left as an exercise for the reader, but it follows easily from the implementation of indices.
(Before C++17 you’d have to write the following instead:)
for (auto&& items : zip(containerA, containerB))
get<0>(items) = get<1>(items);
i wonder why no one mentioned this:
auto itA = vectorA.begin();
auto itB = vectorB.begin();
while(itA != vectorA.end() || itB != vectorB.end())
{
if(itA != vectorA.end())
{
++itA;
}
if(itB != vectorB.end())
{
++itB;
}
}
PS: if the container sizes don't match, then you may need to put each container specific code into its corresponding if block.
For your specific example, just use
std::copy_n(contB.begin(), contA.size(), contA.begin())
For the more general case, you can use Boost.Iterator's zip_iterator, with a small function to make it usable in range-based for loops. For most cases, this will work:
template<class... Conts>
auto zip_range(Conts&... conts)
-> decltype(boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))))
{
return {boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))};
}
// ...
for(auto&& t : zip_range(contA, contB))
std::cout << t.get<0>() << " : " << t.get<1>() << "\n";
Live example.
However, for full-blown genericity, you probably want something more like this, which will work correctly for arrays and user-defined types that don't have member begin()/end() but do have begin/end functions in their namespace. Also, this will allow the user to specifically get const access through the zip_c... functions.
And if you're an advocate of nice error messages, like me, then you probably want this, which checks if any temporary containers were passed to any of the zip_... functions, and prints a nice error message if so.
There are a lot of ways to do specific things with multiple containers as provided in the algorithm header. For instance, in the example you've given, you could use std::copy instead of an explicit for loop.
On the other hand, there isn't any built-in way to generically iterate multiple containers other than a normal for loop. This isn't surprising because there are a lot of ways to iterate. Think about it: you could iterate through one container with one step, one container with another step; or through one container until it gets to the end then start inserting while you go through to the end of the other container; or one step of the first container for every time you completely go through the other container then start over; or some other pattern; or more than two containers at a time; etc ...
However, if you wanted to make your own "for_each" style function that iterates through two containers only up to the length of the shortest one, you could do something like this:
template <typename Container1, typename Container2>
void custom_for_each(
Container1 &c1,
Container2 &c2,
std::function<void(Container1::iterator &it1, Container2::iterator &it2)> f)
{
Container1::iterator begin1 = c1.begin();
Container2::iterator begin2 = c2.begin();
Container1::iterator end1 = c1.end();
Container2::iterator end2 = c2.end();
Container1::iterator i1;
Container2::iterator i2;
for (i1 = begin1, i2 = begin2; (i1 != end1) && (i2 != end2); ++it1, ++i2) {
f(i1, i2);
}
}
Obviously you can make any kind of iterations strategy you want in a similar way.
Of course, you might argue that just doing the inner for loop directly is easier than writing a custom function like this ... and you'd be right, if you are only going to do it one or two times. But the nice thing is that this is very reusable. =)
In case when you need to iterate simultaneously over 2 containers only, there is an extended version of standard for_each algorithm in boost range library, e.g:
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/bind.hpp>
#include <boost/range/algorithm_ext/for_each.hpp>
void foo(int a, int& b)
{
b = a + 1;
}
int main()
{
std::vector<int> contA = boost::assign::list_of(4)(3)(5)(2);
std::vector<int> contB(contA.size(), 0);
boost::for_each(contA, contB, boost::bind(&foo, _1, _2));
// contB will be now 5,4,6,3
//...
return 0;
}
When you need to handle more than 2 containers in one algorithm, then you need to play with zip.
another solution could be capturing a reference of the iterator of the other container in a lambda and using post increment operator on that. for example simple copy would be:
vector<double> a{1, 2, 3};
vector<double> b(3);
auto ita = a.begin();
for_each(b.begin(), b.end(), [&ita](auto &itb) { itb = *ita++; })
inside lambda you can do whatever with ita and then increment it. This easily extends to the multiple containers case.
A range-library provides this and other very helpful functionality. The following example uses Boost.Range. Eric Niebler's rangev3 should be a good alternative.
#include <boost/range/combine.hpp>
#include <iostream>
#include <vector>
#include <list>
int main(int, const char*[])
{
std::vector<int> const v{0,1,2,3,4};
std::list<char> const l{'a', 'b', 'c', 'd', 'e'};
for(auto const& i: boost::combine(v, l))
{
int ti;
char tc;
boost::tie(ti,tc) = i;
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}
C++17 will make this even better with structured bindings:
int main(int, const char*[])
{
std::vector<int> const v{0,1,2,3,4};
std::list<char> const l{'a', 'b', 'c', 'd', 'e'};
for(auto const& [ti, tc]: boost::combine(v, l))
{
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}
I'm a bit late too; but you can use this (C-style variadic function):
template<typename T>
void foreach(std::function<void(T)> callback, int count, ...) {
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
std::vector<T> v = va_arg(args, std::vector<T>);
std::for_each(v.begin(), v.end(), callback);
}
va_end(args);
}
foreach<int>([](const int &i) {
// do something here
}, 6, vecA, vecB, vecC, vecD, vecE, vecF);
or this (using a function parameter pack):
template<typename Func, typename T>
void foreach(Func callback, std::vector<T> &v) {
std::for_each(v.begin(), v.end(), callback);
}
template<typename Func, typename T, typename... Args>
void foreach(Func callback, std::vector<T> &v, Args... args) {
std::for_each(v.begin(), v.end(), callback);
return foreach(callback, args...);
}
foreach([](const int &i){
// do something here
}, vecA, vecB, vecC, vecD, vecE, vecF);
or this (using a brace-enclosed initializer list):
template<typename Func, typename T>
void foreach(Func callback, std::initializer_list<std::vector<T>> list) {
for (auto &vec : list) {
std::for_each(vec.begin(), vec.end(), callback);
}
}
foreach([](const int &i){
// do something here
}, {vecA, vecB, vecC, vecD, vecE, vecF});
or you can join vectors like here: What is the best way to concatenate two vectors? and then iterate over big vector.
I personally prefer using what is already in the STL (in the <algorithm> header) if possible. std::transform has a signature that can take two input iterators. So at least for the case of two input containers you could do:
std::transform(containerA.begin(), containerA.end(), containerB.begin(), outputContainer.begin(), [&](const auto& first, const auto& second){
return do_operation(first, second);
});
Note that the outputContainer can also be one of the input containers. But one limitation is that you cannot do a post update operation if you are modifying one of the containers in place.
The answer is here!... when C++23 comes.
#include <algorithm>
#include <forward_list>
#include <ranges>
#include <array>
#include <iostream>
int main()
{
auto foos = std::to_array({ 1, 2, 3, 4, 5 });
auto woos = std::to_array({ 6, 7, 8, 9, 10 });
auto fooswoos = std::views::zip(foos,woos);
for(auto [foo, woo] : fooswoos) {
woo += foo;
}
std::ranges::for_each(woos, [](const auto& e) { std::cout << e << '\n'; });
return 0;
}
So, what's happening?
We are constructing a special "view". This view allows us to look at containers as if they were other structures without actually doing any copying or anything like that. Using a structured binding we are able to take a reference to each aligning element per iteration and do whatever we want to it (and safely)
Check it out on compiler explorer right now!
Here is one variant
template<class ... Iterator>
void increment_dummy(Iterator ... i)
{}
template<class Function,class ... Iterator>
void for_each_combined(size_t N,Function&& fun,Iterator... iter)
{
while(N!=0)
{
fun(*iter...);
increment_dummy(++iter...);
--N;
}
}
Example usage
void arrays_mix(size_t N,const float* x,const float* y,float* z)
{
for_each_combined(N,[](float x,float y,float& z){z=x+y;},x,y,z);
}

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';
} );
}