Calling a function on every element of a C++ vector

64,923

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;
}   
Share:
64,923
vikaspraj
Author by

vikaspraj

Updated on August 31, 2021

Comments

  • vikaspraj
    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
    ervinbosenbacher about 12 years
    This syntax is not yet supported by vs2011 for example. At least not my copy.But +1.
  • chris
    chris about 12 years
    @xebo, ah, that sucks seeing as how this is one of the best features of C++11 imo.
  • Steve Jessop
    Steve Jessop about 12 years
    This is the answer I was looking for, transform is closer to Python's map than for_each is, since map generates a list of outputs, whereas for_each calls a function but discards the outputs.
  • chris
    chris over 11 years
    For any future visitors, ranged-for was added to Visual Studio 2012.
  • Alex Bitek
    Alex Bitek over 11 years
    How 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
    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 in for_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
    abcd over 8 years
    would one expect speed improvements from using this (as opposed to the loop)?
  • Alexis Wilke
    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
    sanjivgupta over 3 years
    std::for_each(v.begin(), v.end(), &foo); OR std::for_each(v.begin(), v.end(), foo);
  • KulaGGin
    KulaGGin over 2 years
    Why 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
    KulaGGin over 2 years
    Or not use lambda and use a range-based for loop: for(int& n: nums) n++;. Less code - easier to understand.
  • Jerry Coffin
    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
    KulaGGin over 2 years
    Oops, sorry, my bad, I missed that. I did read the title and skimmed through the text.
  • gordon_freeman
    gordon_freeman almost 2 years
    This should be the top answer imo.