我正在将矢量的元素“分组”到地图中,有没有比我目前的方法更有效或更优雅的方法来做到这一点?- 我觉得它在代码方面相当繁琐,并且在性能方面不是最佳的。
我来自 C#,我通常会使用以下方法解决这种情况:
var groupedObservations = observations.GroupBy(o => o.x, o => o.y,o => o.z);
在我当前的 C++ 中,我首先对包含所有元素的向量进行排序,然后使用 if 语句确定何时应该开始新组并将所有后续“相等”元素推入该组。
我目前的代码如下;
struct Observation { int id; double x,y,z; }
vector<std::shared_ptr<Observation>> observations;
..code that fills observations from csv is omitted ..
map<int,vector<shared_ptr<Observation>>> groupedObservations;
std::sort(observations.begin(), observations.end(), sorting_functor());
int groupId = 0;
double x =0 ,y =0 ,z = 0;
for(shared_ptr<Observation> &observation: observations)
{
if(!(x == record->x && y== observation->y && z == observation->z))
{
groupId++; //coordinates different; new group.
x = observation->x;
y = observation->y;
z = observation->z;
}
groupedObservations[groupId].push_back(observation);
}
为完整起见,排序函子如下:
struct sorting_functor
{
bool operator()(const shared_ptr<Observation> &a, shared_ptr<Observation> &b) const
{
return (a->x < b->x) && (a->y < b->y) && (a->z < b->z);
}
};
一个工作示例:
#include <unordered_set>
#include <iostream>
#include <boost/functional/hash.hpp>
#include <tuple>
struct Observation { int id; double x,y,z; };
namespace std
{
template<typename... T>
struct hash<tuple<T...>>
{
size_t operator()(tuple<T...> const& arg) const noexcept {
return boost::hash_value(arg);
}
};
template<>
struct hash<Observation>
{
size_t operator()(const Observation& o) const
{
tuple<double, double, double> t{o.x, o.y, o.z};
return hash<tuple<double, double, double> >()(t);
}
};
}
std::ostream& operator<<(std::ostream& os, Observation o) {
return os<<o.id<<' '<<o.x<<' '<<o.y<<' '<<o.z;
}
bool operator==(const Observation& a, const Observation& b) {
return a.x==b.x && a.y==b.y && a.z==b.z;
}
int main(int argc, char *argv[])
{
std::vector<Observation> a = {
{1, 1.0,1.0,1.1},
{2, 1.0,1.0,1.1},
{3, 3.0,3.0,3.3},
{4, 1.0,1.0,1.1},
{5, 3.0,3.0,3.3},
{6, 5.0,5.0,5.5},
{7, 5.0,5.0,5.5},
{8, 5.0,5.0,5.5},
{9, 2.0,2.0,2.2},
{10,2.0,2.0,2.2},
{11,5.0,5.0,5.5},
{12,4.0,4.0,4.4},
};
std::unordered_multiset<Observation> words;
words.insert(a.begin(), a.end());
for(auto it = words.begin(); it != words.end(); )
{
auto cnt = words.count(*it);
for(auto i=0;i<cnt;i++)
std::cout << *it++ << '\n';
std::cout<<'\n';
}
return 0;
}
这使
10 2 2 2.2
9 2 2 2.2
11 5 5 5.5
8 5 5 5.5
7 5 5 5.5
6 5 5 5.5
5 3 3 3.3
3 3 3 3.3
12 4 4 4.4
4 1 1 1.1
2 1 1 1.1
1 1 1 1.1
您也可以像以前一样对向量进行排序,然后使用https://github.com/Dobiasd/FunctionalPlus/blob/master/include/fplus/split.hpp,这为您提供了非常干净的代码风格。
auto vector_of_vector = fplus::group(your_vector);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句