我正在分组'将矢量元素转换成地图,是否有更高效或更优雅的方式来做,而不是我目前的apporach? - 我认为它代码相当麻烦,并且在性能方面不是最佳的。
我来自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);
}
};
答案 0 :(得分:1)
一个工作示例:
#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);