在 C++ 向量的每个元素上调用函数

Posted

技术标签:

【中文标题】在 C++ 向量的每个元素上调用函数【英文标题】:Calling a function on every element of a C++ vector 【发布时间】:2012-05-09 12:49:49 【问题描述】:

在 C++ 中,有没有一种方法可以在向量的每个元素上调用函数,而不使用遍历所有向量元素的循环?类似于 Python 中的“地图”。

【问题讨论】:

【参考方案1】:

是的: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);

【讨论】:

人们会期望使用这个(而不是循环)提高速度吗? @dbliss,for_each() 的实现很可能是一个循环,因为它使用模板,所以应该没有区别。但是,使用 C++17,它们可能会引入对您完全透明的并行性,并且很可能最终会更快地开始。 std::for_each(v.begin(), v.end(), &foo);或 std::for_each(v.begin(), v.end(), foo);【参考方案2】:

您已经收到多个提到 std::for_each 的答案。

虽然这些回答了您提出的问题,但我想补充一点,至少根据我的经验,std::for_each 是标准算法中最不有用的

我使用(例如)std::transform,基本上是a[i] = f(b[i]);result[i] = f(a[i], b[i]);std::for_each 更频繁。许多人经常使用std::for_each 来打印集合的元素;为此,std::copystd::ostream_iterator 作为目的地效果更好。

【讨论】:

这是我一直在寻找的答案,transformfor_each 更接近 Python 的 map,因为 map 生成输出列表,而 for_each 调用函数但丢弃输出。 为什么不使用基于范围的 for(const auto& item : myCollection)?如果您在类或头文件/源文件中有另一个函数,或者当您使用 lambda 时,只需更少的代码。 @KulaGGin:主要是因为问题指定:“......不使用遍历所有向量元素的循环?”诚然,这可能不是最合理的要求,但是当问题具体是关于不使用循环时建议循环并不能真正回答问题。 哎呀,对不起,我的错,我错过了。我确实阅读了标题并浏览了文本。【参考方案3】:

在 C++ 11 上:您可以使用 lambda。例如:

std::vector<int> nums3, 4, 2, 9, 15, 267;

std::for_each(nums.begin(), nums.end(), [](int &n) n++; );

参考:http://en.cppreference.com/w/cpp/algorithm/for_each

【讨论】:

或者不使用 lambda 并使用基于范围的 for 循环:for(int&amp; n: nums) n++;。更少的代码 - 更容易理解。【参考方案4】:

如果你有 C++11,还有一个更短的方法:ranged-based for。它的目的正是如此。

std::vector<int> v 1,2,3,4,5;

for (int element : v)
    std::cout << element; //prints 12345

您也可以在适当的时候对其应用引用和 const,或者在类型较长时使用 auto。

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

输出:

123
456

【讨论】:

例如,vs2011 尚不支持此语法。至少不是我的副本。但是 +1。 @xebo,啊,看到这是 C++11 imo 的最佳功能之一,真是太糟糕了。 对于未来的访问者,Visual Studio 2012 中添加了 ranged-for。 这如何回答这个问题?您在代码中的哪个位置将函数应用于 std::vector 的每个元素?我只看到迭代。此外,您的第一个示例复制元素,第二个示例通过 const & 传递它们,因此任何修改都在副本上完成或根本无法完成。 @BadDesign,从技术上讲,输出它是应用一个函数,operator&lt;&lt;(std::cout, element)。我这篇文章的主要目标是向这种语法打开 OP(以及任何未来的访问者)。没有说明不想循环的原因,也可能是不想全部输入。 for_each 中也存在一个循环。第二个例子就是这样 - 一个例子。它表明您可以使用或,这使人们可以随意更改它。此外,谁说你需要修改元素才能在其上调用函数?【参考方案5】:

使用for_each:

// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void myfunction (int i) 
  cout << " " << i;


struct myclass 
  void operator() (int i) cout << " " << i;
 myobject;

int main () 
  vector<int> myvector;
  myvector.push_back(10);
  myvector.push_back(20);
  myvector.push_back(30);

  cout << "myvector contains:";
  for_each (myvector.begin(), myvector.end(), myfunction);

  // or:
  cout << "\nmyvector contains:";
  for_each (myvector.begin(), myvector.end(), myobject);

  cout << endl;

  return 0;

【讨论】:

【参考方案6】:

OP 提到了 Python 中的 map 函数。

这个 Python 函数实际上将一个函数应用于列表(或可迭代)的每个元素,并返回一个收集所有结果的列表(或可迭代)。

换句话说,它做了这样的事情:

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), ...] 

因此,与 Python 映射最接近的 C++ 标准库实际上是 std::transform(来自 &lt;algorithm&gt; 标头)。

示例用法如下:

#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;
   

【讨论】:

【参考方案7】:

您可以使用std::for_each,它采用一对迭代器和一个函数或函子。

【讨论】:

【参考方案8】:

如果有人更喜欢它们,我想我会分享 for_eachtransformstd::ranges 等价物:

std::vector<int> v;

std::ranges::for_each(v,[](const auto& n) );

const auto squared = v | std::views::transform([](const auto& n)  return n*2; );

在 Godbolt 上运行:https://godbolt.org/z/zYME6b

【讨论】:

以上是关于在 C++ 向量的每个元素上调用函数的主要内容,如果未能解决你的问题,请参考以下文章

C++ 从函数调用的多次返回中构建字符串向量的最佳方法

C++ 为每个元素调用任意函数

通过引用函数传递向量,但更改不会持续

在数组 c++ 上调用排序函数

模板化成员函数不能从同一个类调用非模板化成员函数,C++

vector 如何在特定位置调用复制构造函数?