Calling a function on every element of a C++ vector
Solution 1
Yes: std::for_each
.
#include <algorithm> //std::for_each
void foo(int a) {
std::cout << a << "\n";
}
std::vector<int> v;
...
std::for_each(v.begin(), v.end(), &foo);
Solution 2
You've already gotten several answers mentioning std::for_each
.
While these respond to the question you've asked, I'd add that at least in my experience, std::for_each
is about the least useful of the standard algorithms.
I use (for one example) std::transform
, which is basically a[i] = f(b[i]);
or result[i] = f(a[i], b[i]);
much more frequently than std::for_each
. Many people frequently use std::for_each
to print elements of a collection; for that purpose, std::copy
with an std::ostream_iterator
as the destination works much better.
Solution 3
On C++ 11: You could use a lambda. For example:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });
ref: http://en.cppreference.com/w/cpp/algorithm/for_each
Solution 4
If you have C++11, there's an even shorter method: ranged-based for. Its purpose is exactly this.
std::vector<int> v {1,2,3,4,5};
for (int element : v)
std::cout << element; //prints 12345
You can also apply references and const to it as well, when appropriate, or use auto when the type is long.
std::vector<std::vector<int>> v {{1,2,3},{4,5,6}};
for (const auto &vec : v)
{
for (int element : vec)
cout << element;
cout << '\n';
}
Output:
123
456
Solution 5
The OP mentions the map
function in Python.
This Python function actually applies a function to every element of a list (or iterable) and returns a list (or iterable) that collects all results.
In other words, it does something like this:
def f( x ) :
""" a function that computes something with x"""
# code here
return y
input = [ x1, x2, x3, ... ]
output = map( func, input )
# output is now [ f(x1), f(x2), f(x3), ...]
Hence, the closest C++ standard-library equivalent to Python's map is actually std::transform
(from the <algorithm>
header).
Example usage is as follows:
#include <vector>
#include <algorithm>
using namespace std;
double f( int x ) {
// a function that computes the square of x divided by 2.0
return x * x / 2.0 ;
}
int main( ) {
vector<int> input{ 1, 5, 10 , 20};
vector<double> output;
output.resize( input.size() ); // unfortunately this is necessary
std::transform( input.begin(), input.end(), output.begin(), f );
// output now contains { f(1), f(5), f(10), f(20) }
// = { 0.5, 12.5, 50.0, 200.0 }
return 0;
}
vikaspraj
Updated on August 31, 2021Comments
-
vikaspraj over 2 years
In C++, is there a way to call a function on each element of a vector, without using a loop running over all vector elements? Something similar to a 'map' in Python.
-
ervinbosenbacher about 12 yearsThis syntax is not yet supported by vs2011 for example. At least not my copy.But +1.
-
chris about 12 years@xebo, ah, that sucks seeing as how this is one of the best features of C++11 imo.
-
Steve Jessop about 12 yearsThis is the answer I was looking for,
transform
is closer to Python'smap
thanfor_each
is, sincemap
generates a list of outputs, whereasfor_each
calls a function but discards the outputs. -
chris over 11 yearsFor any future visitors, ranged-for was added to Visual Studio 2012.
-
Alex Bitek over 11 yearsHow does this answer the question? Where in your code do you apply a function to each element of a std::vector ? I only see iteration. Moreover, your first example copies the elements, and the second example passes them by const &, therefore any modifications are done on the copies or can't be done at all.
-
chris over 11 years@BadDesign, Technically, outputting it is applying a function,
operator<<(std::cout, element)
. My main goal with the post was to open the OP (and any future visitors) to this syntax. The reason for not wanting to loop through was not stated and could just as well have been not wanting to type it all out. There's a loop present infor_each
as well. The second example is just that - an example. It shows that you can use either or, which leaves people free to change it as they wish. Besides, who said you need the element to be modifiable to call a function on it? -
abcd over 8 yearswould one expect speed improvements from using this (as opposed to the loop)?
-
Alexis Wilke almost 8 years@dbliss, the implementation of
for_each()
is likely a loop just the same and since it uses templates, there should be no difference. However, with C++17, they may introduce parallelism which would be totally transparent to you and it could very well end up begin faster. -
sanjivgupta over 3 yearsstd::for_each(v.begin(), v.end(), &foo); OR std::for_each(v.begin(), v.end(), foo);
-
KulaGGin over 2 yearsWhy not just use range-based for(const auto& item : myCollection)? Just less code if you have another function in the class or header/source file, or when you use a lambda.
-
KulaGGin over 2 yearsOr not use lambda and use a range-based for loop:
for(int& n: nums) n++;
. Less code - easier to understand. -
Jerry Coffin over 2 years@KulaGGin: Mostly because the question specifies: "...without using a loop running over all vector elements?" Admittedly, that may not be the most reasonable request, but suggesting a loop when the question is specifically about not using a loop wouldn't really answer the question.
-
KulaGGin over 2 yearsOops, sorry, my bad, I missed that. I did read the title and skimmed through the text.
-
gordon_freeman almost 2 yearsThis should be the top answer imo.