"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()
(如果参数衰减为指针)。
我正在实现一个 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()
(如果参数衰减为指针)。