我正在实现一个lambda来对C ++中的2D向量进行规范化。考虑一个3x3矩阵的简单情况。
1 0 1
0 1 0
0 1 1
我的规范化因子是行中非零项的总和。然后将每个条目除以该归一化因子。例如,第1行有2个非零条目,总计为2.因此,我将每个条目除以2.行标准化向量定义如下:
1/2 0 1/2
0 1 0
0 1/2 1/2
此处显示相关的标准化代码(注意MAX_SIZE = 3)。 lambda捕获列表中存在语法错误。
for(int i = 0; i < MAX_SIZE ; i++)
{
transform(matrix[i].begin(),matrix[i].end(),matrix.begin(), [matrix[i].begin()](int x){
return distance(matrix[i].begin(),lower_bound(matrix[i].begin(),matrix[i].end(),x))});
}
我在这里遗漏了什么吗?
答案 0 :(得分:1)
C ++中的lambda捕获列表只能指定要捕获的值的名称,而matrix[i].begin()
不是名称,它是临时值。您可以为其命名,也可以在封闭范围内为其创建变量。很多周围的代码都缺失了,所以我发明了一个工作版本的代码供你剖析:
#include <algorithm>
#include <cstdio>
template<int N>
void normalize(double (&mat)[N][N]) {
std::for_each(std::begin(mat), std::end(mat),
[](double (&row)[N]) {
double sum = std::accumulate(std::begin(row), std::end(row), 0.0);
std::transform(std::begin(row), std::end(row), std::begin(row),
[sum](double x) { return x / sum; });
});
}
template<int N>
void print(const double (&mat)[N][N]) {
std::for_each(std::begin(mat), std::end(mat),
[](const double (&row)[N]) {
std::for_each(std::begin(row), std::end(row),
[](double x) { std::printf(" %3.1f", x); });
std::putchar('\n');
});
}
int main() {
double mat[3][3] = {
{ 1, 0, 1 },
{ 0, 1, 0 },
{ 0, 1, 1 },
};
std::puts("Matrix:");
print(mat);
normalize(mat);
std::puts("Normalized:");
print(mat);
return 0;
}
这是输出:
Matrix: 1.0 0.0 1.0 0.0 1.0 0.0 0.0 1.0 1.0 Normalized: 0.5 0.0 0.5 0.0 1.0 0.0 0.0 0.5 0.5
就C ++代码而言,这段代码有点奇怪,因为它使用lambdas代替循环(或将for
循环与高阶函数混合)。但是你可以看到,通过为每一行(名为row
)创建一个变量,我们可以很容易地遍历该行,而不是在任何地方指定matrix[i]
。
数组参数double (&mat)[N][N]
的奇怪语法是避免指针衰减,这允许我们在函数体中使用begin()
和end()
(如果参数衰减则不起作用)指针)。