我想用 std::transform 替换 for 循环。由于我对算法和 lambda 函数缺乏经验,我想知道这是否是正确的方法
原始代码
for (size_t i=0; i < dataPhase.size(); ++i)
{
dataPhase[i] = fmod(dataPhase[i], pi*1.00001);
}
使用 lambda 进行 std::transform
std::transform(dataPhase.begin(), dataPhase.end(), dataPhase.begin(),
[](double v){return fmod(v, pi*1.00001); }
);
我需要在这里捕获吗?
在这种使用索引的情况下,我可以做什么来替换 for 循环,如以下代码所示:
const int halfsize = int(length/2);
for (size_t i=0; i < length; ++i)
{
axis[i] = int(i) - halfsize;
}
编辑: 我想扩展这个问题(如果允许的话)。
是否可以用不同的东西替换这种情况下的 for 循环
for(std::vector<complex<double> >::size_type i = 0; i != data.size(); i++) {
dataAmplitude[i] = abs(data[i]);
dataPhase[i] = arg(data[i]);
}
这里不是修改原始 vector ,而是将其值用于两个不同的 vector 。
最佳答案
第 1 部分)
此处不需要捕获,因为您仅在 lambda 代码中使用参数 (v) 和全局变量 (pi)。
仅当 lambda 必须访问当前作用域中的变量(即在函数中声明的变量)时才需要捕获。您可以通过引用 (&) 或通过值 (=) 进行捕获。
下面是一个需要“通过引用捕获”的示例,因为“结果”是从 lambda 内部修改的(但它也捕获了“searchValue”):
size_t count(const std::vector<char>& values, const char searchValue)
{
size_t result = 0;
std::for_each(values.begin(), values.end(), [&](const char& v) {
if (v == searchValue)
++result;
});
return result;
}
(在现实世界中,请使用 std::count_if()
甚至 std::count()
)
编译器为每个捕获 lamda 创建一个未命名仿函数(请参阅 this question )。函数的构造函数接受参数并将其存储为成员变量。因此,“按值捕获”始终使用定义 lambda 时元素所具有的值。
下面是编译器可以为我们之前创建的 lambda 生成的代码示例:
class UnnamedLambda
{
public:
UnnamedLambda(size_t& result_, const char& searchValue_)
: result(result_), searchValue (searchValue_)
{}
void operator()(const char& v)
{
// here is the code from the lambda expression
if (v == searchValue)
++result;
}
private:
size_t& result;
const char& searchValue;
};
我们的函数可以重写为:
size_t count(const std::vector<char>& values, const char searchValue)
{
size_t result = 0;
UnnamedLambda unnamedLambda(result, searchValue);
for(auto it = values.begin(); it != values.end(); ++it)
unnamedLambda(*it);
return result;
}
第 2 部分)
如果您需要索引,请继续使用 for 循环。
std::transform 允许处理单个元素,因此不提供索引。还有一些其他算法,例如 std::accumulate,可以处理中间结果,但我不知道任何提供索引的算法。
关于C++ 变换和 lambda - 替换 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45051819/