Loop over all (unordered) pairs of elements in the vector

I have a std::vector some data (points in my case) and I want to iterate over all even pairs of elements. The order of the pair is not important (since I am only interested in the distance from the points). With the classic for loop, what I would like to do would be something like:

 std::vector<double> vec{-1., 3., 5., -8., 123., ...}; for (std::vector<double>::size_type first = 0; first < vec.size(); ++first) { for (std::vector<double>::size_type second = first+1; second < vec.size(); ++second) { // Compute something using std::fabs(vec.at(first)-vec.at(second)) } } 

My question now is that this can be done more elegantly using range-based loops.

+5
source share
2 answers

I would not try to force it into a range-based loop (since creating an inner loop will not be easy), but I will work directly with iterators to clarify the loop body and make the code less dependent on the specific container that you are using:

 for (auto first = vec.begin(); first != vec.end(); ++first){ for (auto second = first + 1; second != vec.end(); ++second){ // Your vec.at(first) is now simply *first. } } 

Note that first + 1 always valid, since first never vec.end() when first + 1 is evaluated.

std::vector::at also required by the C ++ standard to verify that the supplied index is within the bounds of the vector (and throws a std::out_of_range exception if it is not within the bounds), which is an unnecessary overhead for your case.

+3
source

I only provide this answer because the OP wants to do this using a range for loops. It is not more elegant than regular loops.

If your vector does not have duplicate numbers, you can use reverse iteration instead of starting at a certain point in the second loop so that you can use a range based on your iterations.

to reverse iterate over a range based on loops that require an adapter class.

 template <typename It> class reverse_adapter { public: reverse_adapter(It rbegin, It rend) : _rbegin(rbegin), _rend(rend) {} It begin() const { return _rbegin; } It end() const { return _rend; } private: It _rbegin; It _rend; }; template<typename Container> reverse_adapter<typename Container::reverse_iterator> make_reverse(Container& container) { reverse_adapter<typename Container::reverse_iterator> adapter(std::rbegin(container), std::rend(container)); return adapter; } 

And use this adapter to reverse iterate in the second loop.

 for(auto val : vec) { for (auto second_val : make_reverse(vec)) // Start from last to current item in first loop { if (val == second_val) break; // Instead of first + 1 in second loop auto dif = val - second_val; } } 
+1
source

Source: https://habr.com/ru/post/1262748/


All Articles