如何使用STL算法替换for循环?

问题描述

如何用STL算法替换for循环?在这里,我想将向量vals[i]中的vals的值分配给nodeList[i]->val中的nodeList。如果我使用vals[i] * 2来替换它怎么办?

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x),left(nullptr),right(nullptr) {}
};

int main()
{
    TreeNode node1(1);
    TreeNode node2(2);
    TreeNode node3(3);
    node1.left = &node2;
    node1.right = &node3;

    vector<TreeNode*> nodeList = {&node1,&node2,&node3};
    vector<int> vals = {1,3,2};
    for (int i = 0; i < vals.size(); i++) {
        nodeList[i]->val = vals[i];
        // nodeList[i]->val = vals[i] * 2;
    }
}

解决方法

您在这里做什么,一次要遍历两个容器。

尽管在现代C ++中可以对单个容器进行非常整洁的迭代,但是我从内心深处不建议对这两个容器进行迭代-尚未准备好。 This question列出了各种可能的解决方案,但我不确定。

可以在手动维护第二个索引或迭代器的同时尝试远程循环:

  auto i = vals.begin();
  for (auto & node: nodeList) {
    node->val = *i++;
  }

这是更少的代码,并且在迭代std :: deque之类的地方(与std :: vector不同)直接索引的代价很高,因此迭代时会更快。但是将代码保持不变并等待下一个C ++标准也可能是合理的。

,

您的第一种情况是副本,第二种情况是变换。麻烦的是,您需要transform输出迭代器。

auto as_vals = std::views::transform(nodeList,std::mem_fn(&Node::val));
std::copy(vals.begin(),vals.end(),as_vals.begin());
std::transform(vals.begin(),as_vals.begin(),[](int i){ return i * 2; });

或与boost

auto as_val = boost::make_transform_iterator(nodeList.begin(),as_val);
std::transform(vals.begin(),as_val,[](int i){ return i * 2; });

如果您无权使用C ++ 20或boost,则可以编写类似

的内容
template <typename Iterator,typename T>
class member_iterator
{
    Iterator wrapped;
    using base_t = typename std::iterator_traits<Iterator>::value_type;
    T (base_t::*mem);
public

    using value_type = T;
    using pointer = T*;
    using reference = T&;
    using difference_type = typename std::iterator_traits<Iterator>::difference_type;
    using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;

    member_iterator(Iterator wrapped,T (base_t::*mem)) : wrapped(wrapped),mem(mem) {} 

    T & operator*() const { return (*wrapped).*mem; }
    member_iterator& operator++() { ++wrapped; return *this; }
    // etc.
};
,

for循环的标准“算法”为std::for_each。本质上,它是一个for循环的包装器:

std::for_each(begin(nodeList),end(nodeList),[&vals,i = 0](auto& it) mutable {
    it->val = vals[i++];
});

由于您需要一次迭代两个集合,因此仍然需要索引变量(在本示例中为i),或在每次迭代中使用std::distance对其进行计算。 / p>