C++:结构向量的平均值
C++: average of vector of structs
我的结构是一个二维坐标:
template<typename T>
struct coordinate {
std::pair<T, T> coords;
coordinate() : coords({0, 0}) {}
const T x() const { return coords.first; }
const T y() const { return coords.second; }
// functions to set and manipulate x and y
};
我有一个 std::vector<coordinate<double>> vec
并且想要获得向量中 x 和 y 坐标的平均值。
我的方法是(请勿评判)
double x_ = 0.;
double y_ = 0.;
for (auto v : vec) {
x_ += v.x();
y_ += v.y();
}
x_ /= vec.size();
y_ /= vec.size();
我假设有更合适的方法?我尝试寻找 std::accumulate
,但不知道如何访问 std::accumulate
中的结构成员。
我仍然在为 C++ 苦苦挣扎,所以对您的方法进行一些解释会很棒。
std::accumulate
采用 BinaryOperation 将一个元素添加到累加器:
#include <iostream>
#include <vector>
#include <numeric>
template<typename T>
struct coordinate {
std::pair<T, T> coords;
coordinate() : coords({0, 0}) {}
coordinate(T x,T y) : coords(x,y) {}
const T x() const { return coords.first; }
const T y() const { return coords.second; }
};
int main()
{
std::vector<coordinate<double>> vec{{1,1},{2,0}};
auto avg = std::accumulate(vec.begin(),vec.end(),coordinate{0,0},[](const auto& a,const auto& b){
auto ret = a;
ret.coords.first += b.coords.first;
ret.coords.second += b.coords.second;
return ret;
});
std::cout << avg.coords.first << " " << avg.coords.second;
}
但是,这并不比您的循环简单多少。当您定义 operator+
时,情况会有所不同,因为那是 accumulate
默认使用的内容。然后你可以简单地写 std::accumulate(vec.begin(),vec.end(),coords(0,0));
.
请注意,我必须为该示例添加一个构造函数,您仍然必须除以 vec.size
,也许还需要通过 operator/=
.
if my vector would only have doubles, then yes. But I don't get, how to use accumulate, if my vector has structs instead doubles.
如果 T
是某个结构,那么该结构应该实现 operator+
或 operator+=
。如果结构没有任何一个,则对其进行平均是没有意义的。
就像我说的,如果你想对你的类型进行算术运算,你可能想要重载运算符。这样你就可以
#include <numeric>
#include <vector>
template<typename T>
struct coordinate {
std::pair<T, T> coords;
coordinate() : coords({0, 0}) {}
coordinate(T x,T y) : coords(x,y) {}
T x() const { return coords.first; }
T y() const { return coords.second; }
coordinate& operator+=(coordinate const& other){
coords.first += other.coords.first;
coords.second += other.coords.second;
return *this;
}
template<typename D>
coordinate& operator/=(D divider){
coords.first /= divider;
coords.second /= divider;
return *this;
}
};
template<typename T>
coordinate<T> operator+(coordinate<T> lhs, coordinate<T> const& rhs){
return lhs += rhs;
}
template<typename T, typename D>
coordinate<T> operator/(coordinate<T> lhs, D rhs){
return lhs /= rhs;
}
template<typename T>
coordinate<T> average(std::vector<coordinate<T>> const& vec){
if (vec.empty()){
return coordinate<T>{};
}
return std::accumulate(cbegin(vec), cend(vec), coordinate<T>{}) / vec.size();
}
int main()
{
std::vector<coordinate<double>> vec{{1,1},{2,0}};
auto avg = average(vec);
}
我的结构是一个二维坐标:
template<typename T>
struct coordinate {
std::pair<T, T> coords;
coordinate() : coords({0, 0}) {}
const T x() const { return coords.first; }
const T y() const { return coords.second; }
// functions to set and manipulate x and y
};
我有一个 std::vector<coordinate<double>> vec
并且想要获得向量中 x 和 y 坐标的平均值。
我的方法是(请勿评判)
double x_ = 0.;
double y_ = 0.;
for (auto v : vec) {
x_ += v.x();
y_ += v.y();
}
x_ /= vec.size();
y_ /= vec.size();
我假设有更合适的方法?我尝试寻找 std::accumulate
,但不知道如何访问 std::accumulate
中的结构成员。
我仍然在为 C++ 苦苦挣扎,所以对您的方法进行一些解释会很棒。
std::accumulate
采用 BinaryOperation 将一个元素添加到累加器:
#include <iostream>
#include <vector>
#include <numeric>
template<typename T>
struct coordinate {
std::pair<T, T> coords;
coordinate() : coords({0, 0}) {}
coordinate(T x,T y) : coords(x,y) {}
const T x() const { return coords.first; }
const T y() const { return coords.second; }
};
int main()
{
std::vector<coordinate<double>> vec{{1,1},{2,0}};
auto avg = std::accumulate(vec.begin(),vec.end(),coordinate{0,0},[](const auto& a,const auto& b){
auto ret = a;
ret.coords.first += b.coords.first;
ret.coords.second += b.coords.second;
return ret;
});
std::cout << avg.coords.first << " " << avg.coords.second;
}
但是,这并不比您的循环简单多少。当您定义 operator+
时,情况会有所不同,因为那是 accumulate
默认使用的内容。然后你可以简单地写 std::accumulate(vec.begin(),vec.end(),coords(0,0));
.
请注意,我必须为该示例添加一个构造函数,您仍然必须除以 vec.size
,也许还需要通过 operator/=
.
if my vector would only have doubles, then yes. But I don't get, how to use accumulate, if my vector has structs instead doubles.
如果 T
是某个结构,那么该结构应该实现 operator+
或 operator+=
。如果结构没有任何一个,则对其进行平均是没有意义的。
就像我说的,如果你想对你的类型进行算术运算,你可能想要重载运算符。这样你就可以
#include <numeric>
#include <vector>
template<typename T>
struct coordinate {
std::pair<T, T> coords;
coordinate() : coords({0, 0}) {}
coordinate(T x,T y) : coords(x,y) {}
T x() const { return coords.first; }
T y() const { return coords.second; }
coordinate& operator+=(coordinate const& other){
coords.first += other.coords.first;
coords.second += other.coords.second;
return *this;
}
template<typename D>
coordinate& operator/=(D divider){
coords.first /= divider;
coords.second /= divider;
return *this;
}
};
template<typename T>
coordinate<T> operator+(coordinate<T> lhs, coordinate<T> const& rhs){
return lhs += rhs;
}
template<typename T, typename D>
coordinate<T> operator/(coordinate<T> lhs, D rhs){
return lhs /= rhs;
}
template<typename T>
coordinate<T> average(std::vector<coordinate<T>> const& vec){
if (vec.empty()){
return coordinate<T>{};
}
return std::accumulate(cbegin(vec), cend(vec), coordinate<T>{}) / vec.size();
}
int main()
{
std::vector<coordinate<double>> vec{{1,1},{2,0}};
auto avg = average(vec);
}