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);
}