Is there a standard implementation of a for_each that does call with the element and the next one in the range?
For example take the range {0, 1, 2, 3, 4, 5}, I would like to call a function f with each element and its successor: {f(0, 1), f(1, 2), f(2, 3), f(3, 4), f(4, 5)}
Note how the last element is left out because it has no successor.
It would also be nice if there was a generalization of this to n successors that get passed with the element itself.
Up to now I have always solved this in terms of a handwritten loop with iterators.
However, I would like to go much more along the lines of C++11 range based for or std::for_each to avoid boiler plate code.
Examples
// today: handwritten loop
for(Range::iterator current = range.begin(); current != range.end(); ++current)
f(*current, *std::next(current));
// near future: wrapped version
for_each_pair(range.begin(), range.end(), f);
// slightly further future: generalized version
for_each_tuple<n>(range.begin(), range.end(), f);
Additional Question
The name of the function could be improved. To me for_each_pair/tuple sounds like all subsets of size n of the range should be returned (which is in itself another problem I would like to solve). So I'd like some suggestions on better names like:
for_each_adjacent<n>
Temporary Solution
I have posted my own solution over at CR. I won't duplicate it here because this is about a standard solution and there are already enough roll-your-own answers.
You could actually abuse std::unique or std::adjacent_find for this: the predicate is called with each consecutive pair in the iterator range, and as long as the predicate always returns false, it won't modify anything or return early.
Disregarding that particular hack, I would implement this as an iterator adapter, not an algorithm. That is, I'd implement a consecutive_tuple_iterator<N> which would return all tuples of N consecutive items. Then you could use it for things like count_if and includes, not just for_each. (It wouldn't be appropriate for most modifying algorithms, though.)
The simplest thing would be to write it as a generic algorithm, then apply it many times.
template< typename FwdIter, typename Func >
Func for_each_pair( FwdIter iterStart, FwdIter iterEnd, Func func )
{
if( iterStart == iterEnd )
return func;
FwdIter iterNext = iterStart;
++iterNext;
for( ; iterNext != iterEnd; ++iterStart, ++iterNext )
{
func( *iterStart, *iterNext );
}
return func;
}
As I was asked why it returns func (rather than void), this is typical of a for_each because of the fact that
func could be an object
It is passed by value.
func may "accumulate" some kind of state, but it is the copy we have made into this algorithm that is accumulating it, not the user's original object. We therefore pass them back the modified "func" object.
With C++ 11 and the new iterator helper functions std::next and std::prev for iterators, the second variant of the standard algorithm std::transform can be used to iterate over adjacent elements.
Here is an example that generates a list of adjacent pairs from a list:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::vector<std::pair<int,int>> num_pairs;
if (!nums.empty()) {
std::transform(
std::begin(nums), std::prev(std::end(nums)),
std::next(std::begin(nums)),
std::back_inserter(num_pairs),
std::make_pair<
decltype(nums)::const_reference,
decltype(nums)::const_reference
>
);
}
Not exactly what you want, but take a look at cpplinq.
int numbers[] = {0, 1, 2, 3, 4, 5};
auto pairs = cpplinq::from_array(numbers)
>> cpplinq::pairwise()
>> cpplinq::to_vector(); // yields (0,1), (1,2), (2,3), (3,4), (4,5)
for(auto p : pairs)
f(p.first, p.second);
look out for C++23 views::slide(n)
vector<int> ints = {1, 2, 3, 4};
auto rg2 = ints | views::slide(2);
/*
{{1, 2}, {2, 3}, {3, 4}}
*/
auto rg3 = ints | views::slide(3);
/*
{{1, 2, 3},{2, 3, 4}}
*/
Related
Hi I have a question on the usage of std::nth_element.
If I want to obtain the k-th largest element from a vector, should it inclusive or exclusive?
int k = 3;
vector<int> nums{1,2,3,4,5,6,7};
std::nth_element(nums.begin(), nums.begin()+k-1, nums.end(), [](int& a, int& b){return a > b;});
int result = nums[k-1]
or
int k = 3
vector<int> nums{1,2,3,4,5,6,7};
std::nth_element(nums.begin(), nums.begin()+k, nums.end(), [](int& a, int& b){return a > b;});
int result = nums[k-1]
It reminds me that when we get a subarray using iterator, it should be exclusive?
for example,
vector<int> sub(nums.begin(), nums.begin()+k);
So, the n for nth_element is also exclusive?
This is the type of question that is best to figure out and understand by playing around with a bunch of examples on your own.
However, I'll try to explain why you're getting the same answer in both of your examples. As explained in cppreference, std::nth_element is a partial sorting algorithm. It only guarantees that, given an iterator to an element n as its second argument:
All of the elements before this new nth element are less than or equal to the elements after the new nth element.
("Less than or equal to" is the default behavior if you don't pass a special comparison function.)
That means if you use nums.begin()+k-1 in one case and nums.begin()+k in another case as the second argument to std::nth_element, then in the latter case the partial sorting algorithm will include one additional item in the sort. In that case, you are dividing the vector between larger and smaller items at a spot one index higher than in the first case. However, the (default) algorithm only guarantees that each of the items in the "small half" of the vector will be smaller than each of the items in the "large half," not that the two halves are sorted within themselves.
In other words, if you've done a partial sort through nums.begin()+k, there is no guarantee that nums[k-1] will be the next-smallest (or in your case, the next-largest) number in the entire vector.
With certain inputs, like your {1, 2, 3, 4, 5, 6, 7}, or {9, 4, 1, 8, 5}, you do happen to get the same answers.
However, with many others, like {1, 4, 9, 8, 5}, the results do not match:
int k = 3;
vector<int> nums{1,4,9,8,5};
auto numsCopy = nums;
// First with +k - 1
std::nth_element(nums.begin(), nums.begin()+k-1, nums.end(), [](int& a, int& b){return a > b;});
// Then with only +k
std::nth_element(numsCopy.begin(), numsCopy.begin()+k, numsCopy.end(), [](int& a, int& b){return a > b;});
cout << nums[k-1]; // 5
cout << numsCopy[k-1]; // 9
Demo
Can you figure out why that is?
Also, to clearly answer your question about inclusive vs exclusive, as #Daniel Junglas pointed out in the comments, the second argument to std::nth_element is meant to point directly to the item you wish to be changed. So if it helps you, you can think of that as "inclusive." This is different from the third argument to std::nth_element, the end iterator, which is always exclusive since .end() points beyond the last item in the vector.
Add element to function in place C++
Python code:
l1 = [1, 2, 3]
l2 = l1 + [4]
print(l2) #[1, 2, 3, 4]
l3 = l1+l2
print(l3) #[1, 2, 3, 1, 2, 3, 4]
Is there a way to do this in C++
You clarified in a comment that you want to do it "in place". In C++17 there isn't an operator or function in the standard library for concatenating two vectors (or containers), but it is pretty easy to create one yourself:
template <class T>
std::vector<T> concat(const std::vector<T>& v1, const std::vector<T>& v2)
{
auto res = v1;
res.insert(res.end(), v2.begin(), v2.end());
return res;
}
In C++20 all this changes as we will get ranges.
Until then you can use the ranges-v3 library (on which the standard ranges are based):
views::concat(v1, v2);
This returns a range. That should be enough as you should take range views as parameters or at least iterators. The advantage is that views are lazy. They don't do the actual transformations until you iterate over them and don't create new containers. If you however still need a vector you can do that like this:
#include <range/v3/view.hpp>
using namespace ranges;
auto test()
{
std::vector v1{10, 20, 30};
std::vector v2{1, 2, 3, 4, 5};
auto v = views::concat(v1, v2) | to<std::vector>();
}
There has been a comment about creating an overloaded operator+ instead of the function. That would be a bad idea for a few reasons:
Overloading an operator with only standard classes as parameters is a bad idea as you can't open namespace std to define it there and defining it elsewhere will cause problems with ADL.
Second, even if you could, a golden rule is to overload an operator to do expected things. In this case, an operator+ would be expected by (some/most) people to do element-wise addition.
I believe you're trying to add an element to a vector in c++.
vector<int> v; // { }
v.push_back(10); // { 10 }
To append one vector to another vector, you could use insert
vector<int> v = { 11, 12 };
vector<int> v2 = { 13, 14 };
v.insert(v.end(), v2.begin(), v2.end()); // { 11, 12, 13, 14 }
The first parameter to insert is an iterator pointing to where you want the second vector's elements to be inserted. The 2nd and 3rd parameters are the iterators pointing to the beginning and end of the second vector, they denote the boundaries of which elements to insert into the first vector.
This operation effectively appends the second vector into the first vector.
I have some (templated) iterator pair Iterator begin1 and Iterator end1. I have a function foo, with signature
template <typename ForwardIterator>
void foo(ForwardIterator begin, ForwardIterator end);
which does something on that range. Now, I want to have foo act not on the actual range elements, but rather on a transformation of these elements by some lambda or some function bar. I can't use std::transform or otherwise use temorary storage for the transformed values, since that would take up too much space or since I'm not allowed to allocate anything on the heap.
Now, I know I can implement some kind of adapting iterator myself, but I'd rather use something ready-made and not reinvent the wheel.
So, what's a quick and dirty way to get an appropriate adapting iterator pair I can pass for foo to do what I want? i.e. for me to be able to call
foo(magic(begin), magic(end))
or
auto new_pair = magic(begin, end);
foo(new_pair.first, new_pair.second);
?
Eric Niebler's range-v3 library provides a very nice solution for this, and is planned to be included in a future standard. Here's a simple example:
std::vector<int> vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | view::transform([](int x){ return x % 2; });
foo(rng.begin(), rng.end()); // When foo dereferences these iterators, it
// will see: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0].
This is all lazy and efficient, by the way. :)
I'm just wondering whether there is a simple, quick way to insert the elements of a vector of vectors inside a vector.
For example:
std::vector<std::vector<double> > vals
{
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6}
};
std::vector<double> myvector;
so myvector would then contain: 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6
I've tried using insert and push_back but had no luck.
Edit:
I have used:
myvector.insert(vals.begin(), vals.end()); - No matching member function to call to 'insert'
Try
// c++11
for(auto && v : vals){
myvector.insert(myvector.end(), v.begin(), v.end());
}
// non c++11
for(std::vector<std::vector<double> >::const_iterator it = vals.begin(), end = vals.end(); it != end; ++it){
myvector.insert(myvector.end(), it->begin(), it->end());
}
Depending on how your vector of vectors is built in the first place, there may be a more efficient way to approach this.
If your sub-vectors are all the same length (as appears to be the case from the code example), then the best thing may be to view myvector as a 2D array and build directly into this buffer.
If the sub-vector lengths can vary, but the code that builds your vector of vectors only ever actually adds stuff at the end, then you can use something like the 'collapsed vector vector' class I describe here to build this data, instead of a vector of vectors.
(And after that, again, your data is already in the kind of contiguous buffer you are looking for.)
Either way, if performance or memory footprint are important here then avoiding the vector of vector construct can eliminate a lot of buffer manipulation overhead, and work out as quite a significant optimisation.
If you want to insert all of the elements of vals into a single vector:
Brute Force Method
for (int i = 0; i < vals.size(); ++i)
{
for (int j = 0; j < vals[i].size(); ++j)
{
myvector.push_back(vals[i][j]);
}
}
More Elegant Method
struct AddVector
{
std::vector<double> myvector;
void operator()(const std::vector<int>& a)
{
std::copy(a.begin(), a.end(), std::back_inserter(myvector));
}
};
// somewhere in your code
AddVector av;
std::for_each(vals.begin(), vals.end(), av);
myvector.swap(av.myvector);
The variable vals is a vector of vectors, but myvector is a vector of doubles. Trying to insert from the first into the second will not work as the contained types are different (std::vector<double> versus double).
Instead you have to manually insert from each sub-vector of vals into myvector.
resize myvector to the size of the sum of the sizes of the vectors in vals. For every vector in vals concat it to myvector. To get a idea how to concat:
Concatenating two std::vectors
I'm using a vector in a C++ program and I need to pass a part of that vector to a function.
If it was C, I would need to do the following (with arrays):
int arr[5] = {1, 2, 3, 4, 5};
func(arr+2); // Pass the part of the array {3, 4, 5}
Is there any other way than creating a new vector with the last part?
A common approach is to pass iterator ranges. This will work with all types of ranges, including those belonging to standard library containers and plain arrays:
template <typename Iterator>
void func(Iterator start, Iterator end)
{
for (Iterator it = start; it !=end; ++it)
{
// do something
}
}
then
std::vector<int> v = ...;
func(v.begin()+2, v.end());
int arr[5] = {1, 2, 3, 4, 5};
func(arr+2, arr+5);
Note: Although the function works for all kinds of ranges, not all iterator types support the increment via operator+ used in v.begin()+2. For alternatives, have a look at std::advance and std::next.
Generically you could send iterators.
static const int n[] = {1,2,3,4,5};
vector <int> vec;
copy (n, n + (sizeof (n) / sizeof (n[0])), back_inserter (vec));
vector <int>::iterator itStart = vec.begin();
++itStart; // points to `2`
vector <int>::iterator itEnd = itStart;
advance (itEnd,2); // points to 4
func (itStart, itEnd);
This will work with more than just vectors. However, since a vector has guaranteed contigious storage, so long as the vector doesn't reallocate you can send the addresses of elements:
func (&vec[1], &vec[3]);
The latest (C++20) approach is to use std::span. Create a std::span that views a part of std::vector and pass it to functions. Note: the elements must be continuous in memory to use std::span on a container, and std::vector is continuous in memory.
#include <span>
std::vector<int> int_vector = {1, 2, 3, 4, 5};
std::span<int> a_span(int_vector.data() + 2, int_vector.size() - 2);
for(const int a : a_span);
for(const int& a : a_span);
function(a_span);
As of C++20, I would make use of a range from the Ranges library, because it offers a variety of range adaptors for creating different views on you vector. For your use case, I would use the range adaptor std::views::drop as follows:
int main() {
std::vector<int> arr {1, 2, 3, 4, 5};
// Ignore the first two elements and pass only {3, 4, 5} to func().
func(arr | std::views::drop(2));
return 0;
}
This way you don't have to bother with interators or pointer/iterator arithmetic.
Also, no temporary vector is created for your shortened arr, because the view adaptor drop() creates a range that doesn't contain elements. The resulting range is just a view over the original vector arr, but with a customized iteration behavior.
For the declaration of func() I would use the placeholder type auto for the function parameter, because the type of the resulting range is quite complex. This makes func() a function template, though:
void func(auto range) {
for (int i : range)
std::cout << i << std::endl;
}
(Alternatively, you could pass arr by reference to func() and apply the range adaptor inside func().)
Output:
3
4
5
Code on Wandbox
std::vector<char> b(100);
send(z,&b[0],b.size(),0);
Try out this.
Read this too.
As some others already stated you can use iterators for that. You'll have to pass the start of the sequence and the end of the sequence to your worker function.
If you need more flexibility, you should take a look at slice. With slice you can for example retrieve every n-th entry of the vector.
I was also stuck to same problem.I found one really nice trick.Suppose you want to find the minimum in range L to R (both inclusive) of arr then you can do something like this:
vector<int>arr = {4,5,1,3,7};
int minVal = *min_element(begin(arr)+L,begin(arr)+(R+1));
Means you pass the complete array and range and then you can apply the above trick.