获取 c++ 中浮点数向量的向量的逐元素平均值
Get element-wise mean of vector of vectors of floats in c++
假设我有以下大小相同的向量:
std::vector<float> a({1, 1, 1});
std::vector<float> b({2, 2, 2});
std::vector<float> c({4, 4, 5});
我想得到逐元素的平均向量:
std::vector<float> mean({2.333, 2.333, 2.666});
实现这一目标的最优雅方法是什么?我可以编写 for 循环来做到这一点,但想知道是否有更好的方法可以做到这一点。
另请注意,我希望解决方案扩展到任意数量的向量(为了举例说明,我使用了三个向量(
对于元素级操作,您应该使用 std::valarray
.底漆:
std::valarray<float> a { 1, 1, 1 };
std::valarray<float> b { 2, 2, 2 };
std::valarray<float> c { 4, 4, 5 };
std::valarray<float> mean = (a + b + c) / 3.f;
std::vector<float> v{std::begin(mean), std::end(mean)}
这适用于 GCC 7.2.1 的 C++11 模式。现在你还没有指定你如何在载体中喂食,所以你想要什么还不清楚。如果您事先知道要处理多少个向量,这应该有效:
std::valarray<float> foo(std::vector<std::valarray<float>> args) {
assert(args.size() > 0);
// sum MUST be initialized with a size
// and in this case, all sizes must be the same
// otherwise += is undefined behavior
std::valarray<float> sum(args[0].size());
for (auto c : args) {
sum += c;
}
return (sum / (float)args.size());
}
如果你的内部向量总是具有相同的大小,std::vector
似乎不是一个好的选择(它会产生不必要的许多小堆分配并降低数据局部性(。最好使用std::array
,或者定义自己的class Vec
:
#include <vector>
#include <array>
#include <numeric>
#include <algorithm>
template <typename T, std::size_t N>
struct Vec : std::array<T, N> {
Vec() = default;
explicit Vec(std::array<T, N> const& a): std::array<T, N>(a) {}
static Vec zero() { return Vec(std::array<T, N>{0}); }
Vec operator + (Vec const& rhs) const {
Vec result;
std::transform(std::begin(*this), std::end(*this), std::begin(rhs), std::begin(result), std::plus<T>());
return result;
}
template <typename T2>
Vec operator / (T2 const& rhs) const {
Vec result;
std::transform(std::begin(*this), std::end(*this), std::begin(result), [&](T const& lhs) { return lhs/rhs; });
return result;
}
};
Vec<float, 3> elementwise_mean(std::vector<Vec<float, 3>> vecvec) {
return std::accumulate(std::begin(vecvec), std::end(vecvec), Vec<float, 3>::zero()) / vecvec.size();
}
或者你可以偷懒,使用像 eigen3 这样的专用库。
实现OP目标的"最优雅方式">是什么,恐怕是一个见仁见智的问题,但我们肯定可以用标准库中的算法替换大多数显式for
循环。
向量可能不是每个用例的最佳数据结构,此外,按列遍历此对象可能不是很适合缓存。但是,即使它是强制性的,我们仍然可以通过逐行遍历容器,在临时向量中累积每列的总和并最终计算平均值来执行所有需要的计算。
此代码段显示了一个可能的(稍微更通用的(实现:
#include <iostream>
#include <vector>
#include <array>
#include <iterator>
#include <stdexcept>
#include <algorithm>
#include <functional>
template<class ReturnType = double, class Container>
auto elementwise_mean(Container const& mat)
{
using MeansType = std::vector<ReturnType>;
using DistType = typename MeansType::iterator::difference_type;
auto it_row = std::begin(mat);
auto n_rows = std::distance(it_row, std::end(mat));
if ( n_rows == 0 )
throw std::runtime_error("The container is empty");
MeansType means(std::begin(*it_row), std::end(*it_row));
const DistType row_size = means.size();
if ( row_size == 0 )
throw std::runtime_error("The first row is empty");
std::for_each(
++it_row, std::end(mat),
[&means, row_size](auto const& row) {
if ( row_size != std::distance(std::begin(row), std::end(row)) )
throw std::runtime_error("A row has a wrong length");
std::transform(
means.begin(), means.end(), std::begin(row),
means.begin(), std::plus()
);
}
);
std::for_each(means.begin(), means.end(), [n_rows](auto & a){ a /= n_rows; });
return means;
}
template<class Container> void print_out(Container const& c);
int main()
{
std::vector<std::vector<double>> test {
{1.0, 1.0, 1.0},
{2.0, 2.0, 2.0},
{4.0, 4.0, 5.0}
};
auto means = elementwise_mean(test);
print_out(means); // --> 2.33333 2.33333 2.66667
std::array<int, 4> test2[2] = {
{{1, 3, -5, 6}},
{{2, 5, 6, -8}},
};
auto means2 = elementwise_mean<float>(test2);
print_out(means2); // --> 1.5 4 0.5 -1
auto means3 = elementwise_mean<int>(test2);
print_out(means3); // --> 1 4 0 -1
}
template<class Container>
void print_out(Container const& c)
{
for ( const auto x : c )
std::cout << ' ' << x;
std::cout << 'n';
}
相关文章:
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 在 C++ 中输出枚举类类型的向量元素
- 用向量的向量元素初始化向量的空向量
- 为什么不允许使用可变长度数组作为向量元素?
- 在函数中传递向量元素
- 使用 Rcpp 加速替换迭代算法中的列表和向量元素是否合法?
- 返回向量元素的 l 值的正确方法是什么?
- 当向量增长时,指向向量元素的C++指针是否无效
- 如何在C++中从一个向量元素减去std::unorderede_map向量元素并更新它
- C++:向量元素赋值导致访问冲突
- 将向量元素与字符串元素进行比较,而不初始化向量
- 从2D矢量中找出最小尺寸的向量元素的更好方法
- 当我尝试将一个向量元素的值分配给另一个向量元素时,为什么我的应用程序会崩溃
- 使用递归C++向量元素的总和
- 如何查找为数组中的最低值编制索引的向量元素
- 限制指针访问STL ::向量元素
- 访问索引指向向量元素时的seg故障 - 做错了什么
- 如何使用指针访问向量元素的各个元素
- 向量元素数据损坏了Find()操作
- 将字符值分配给向量元素.C