"Normalize" 使用 lambda 的 C++ 二维向量

"Normalize" a 2D Vector in C++ using lambda

我正在实现一个 lambda 来对 C++ 中的二维向量进行行规范化。考虑 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))});

}

我在这里遗漏了什么吗?

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++ 代码而言,因为它对所有内容都使用 lambda 而不是循环(或者将 for 循环与高阶函数混合)。但是您可以看到,通过为每一行设置一个变量(名为 row),我们可以很容易地遍历该行,而不是在所有地方都指定 matrix[i]

数组参数double (&mat)[N][N]的奇怪语法是为了避免指针衰减,这允许我们在函数体中使用begin()end()(如果参数衰减为指针)。