"规格化"使用lambda的C ++中的2D向量

时间:2016-03-05 02:03:31

标签: c++ vector lambda normalization

我正在实现一个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))});

}

我在这里遗漏了什么吗?

1 个答案:

答案 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()(如果参数衰减则不起作用)指针)。