问题描述
如何用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>