Created
January 31, 2023 19:39
-
-
Save blockspacer/6e3d29f0c081dddb36f779c15cf786eb to your computer and use it in GitHub Desktop.
Equivalent of GROUP BY COUNT using boost multi-index https://stackoverflow.com/questions/73489078/equivalent-of-group-by-count-using-boost-multi-index
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <boost/multi_index_container.hpp> | |
#include <boost/multi_index/composite_key.hpp> | |
#include <boost/multi_index/member.hpp> | |
#include <boost/multi_index/ordered_index.hpp> | |
#include <string> | |
#include <boost/range/adaptors.hpp> | |
#include <vector> | |
#include <iostream> | |
//#include <boost/bind.hpp> | |
#include <boost/range.hpp> | |
#include <boost/foreach.hpp> | |
#include <boost/iterator/filter_iterator.hpp> | |
#include <boost/range/iterator_range.hpp> | |
#include <iostream> | |
using namespace std; | |
using namespace boost; | |
typedef boost::iterator_range<vector<int>::iterator> int_range; | |
/*template< class Range, class Pred > | |
boost::iterator_range< boost::filter_iterator< Pred, typename boost::range_iterator<typenameRange::value_type>::type > > | |
make_filter_range( Range& begin_rng, Range& end_rng, Pred pred ) { | |
return boost::make_iterator_range( | |
boost::make_filter_iterator(pred, begin_rng, end_rng), | |
boost::make_filter_iterator(pred, end_rng, end_rng) ); | |
}*/ | |
template< class Iter, class Range, class Pred > | |
boost::iterator_range< boost::filter_iterator< Pred, typename boost::range_iterator<Range>::type > > | |
make_filter_range( Range& rng, Iter& begin_rng, Iter& end_rng, Pred pred ) { | |
return boost::make_iterator_range( | |
boost::make_filter_iterator(pred, begin_rng, end_rng), | |
boost::make_filter_iterator(pred, end_rng, end_rng) ); | |
} | |
using boost::adaptors::filtered; | |
using namespace boost::multi_index; | |
struct SatData { | |
std::string sat_system; | |
std::string band; | |
int index; | |
uint64_t time; | |
double data; | |
SatData( | |
const std::string& ss, | |
const std::string& b, | |
const int& i, | |
const uint64_t& t, | |
const double& d) : | |
sat_system(ss), band(b), index(i), time(t), data(d) {} | |
}; | |
struct ByGroupID {}; | |
struct ByBand {}; | |
using SatDataset = | |
multi_index_container< | |
SatData, indexed_by< | |
ordered_non_unique< | |
boost::multi_index::tag<ByGroupID>, | |
composite_key< | |
SatData, | |
member<SatData, std::string, &SatData::sat_system>, | |
member<SatData, std::string, &SatData::band>, | |
member<SatData, uint64_t, &SatData::time>, | |
member<SatData, int, &SatData::index> | |
> // composite key | |
> // ordered_not_unique | |
, ordered_non_unique< | |
boost::multi_index::tag<ByBand>, | |
composite_key< | |
SatData, | |
member<SatData, std::string, &SatData::band>, | |
member<SatData, std::string, &SatData::sat_system>, | |
member<SatData, uint64_t, &SatData::time>, | |
member<SatData, int, &SatData::index> | |
> // composite key | |
> // ordered_not_unique | |
> // indexed_by | |
>; // multi_index_container | |
template<typename Iter> | |
void process(Iter first) | |
{ | |
std::cout | |
<< first->sat_system << "\t|" | |
<< first->band << "\t|" | |
<< first->index << "\t|" | |
<< first->time << "\t|" | |
<< first->data << "\t|" | |
<< "\n"; | |
} | |
template<typename Iter> | |
void process(const Iter& start, const Iter& end) | |
{ | |
/*if (start < end) { | |
return; | |
}*/ | |
if (start == end) { | |
//process(start); | |
return; | |
} | |
for(auto first = start, last = end; first != last; first++) { | |
process(first); | |
} | |
} | |
int main() | |
{ | |
SatDataset s = { | |
{"UPD_PLU" , "L1" , 1 , 10, 0.112}, | |
{"GPS" , "L1" , 1 , 11, 0.201}, | |
{"GPS" , "L1" , 1 , 12, 0.100}, | |
{"GPS" , "L2" , 1 , 10, 0.098}, | |
{"GPS" , "L2" , 1 , 11, 0.134}, | |
{"GPS" , "L2" , 1 , 12, 0.167}, | |
{"GPS" , "L2" , 4 , 11, 0.199}, | |
{"GPS" , "L2" , 4 , 12, 0.204}, | |
{"GALILEO" , "E5b" , 2 , 10, 0.056}, | |
{"GLONASS" , "G1" , 1 , 10, 0.123}, | |
{"GLONASS" , "G1" , 1 , 11, 0.222}, | |
{"GLONASS" , "G1" , 2 , 10, 0.115}, | |
}; | |
auto &by_group_id = s.get<ByGroupID>(); | |
//auto filtered_group_id = by_group_id | filtered([](const SatData&){return true;}); | |
//process(range.begin()); | |
for(auto first = by_group_id.begin(), last = by_group_id.end(); first != last; ) { | |
auto next = by_group_id.upper_bound(std::make_tuple( | |
first->sat_system)); | |
std::cout | |
<< "\n====================== GROUP: " | |
<< first->sat_system << "\t|" | |
<< first->band << "\t|" | |
<< first->index << "\t|" | |
<< first->time << "\t|" | |
<< std::distance(first, next) << "====================== \n"; | |
//auto range = boost::make_iterator_range(first, next); | |
//process(filter_range.begin()); | |
//process(filter_range.end()); | |
auto filter_range = make_filter_range(by_group_id, first, next, [](const SatData& elem){return elem.band == "L1";}); | |
process(filter_range.begin(), filter_range.end()); | |
/*std::cout | |
<< "\n====================== GROUP: " | |
<< first->sat_system << "\t|" | |
<< first->band << "\t|" | |
<< first->index << "\t|" | |
<< first->time << "\t|" | |
<< std::distance(first, next) << "====================== \n"; | |
process(first, next);*/ | |
first = next; | |
} | |
auto &by_band = s.get<ByBand>(); | |
//auto filtered_group_id = by_group_id | filtered([](const SatData&){return true;}); | |
//process(range.begin()); | |
for(auto first = by_band.begin(), last = by_band.end(); first != last; ) { | |
auto next = by_band.upper_bound(std::make_tuple( | |
first->band)); | |
std::cout | |
<< "\n====================== BAND: " | |
<< first->sat_system << "\t|" | |
<< first->band << "\t|" | |
<< first->index << "\t|" | |
<< first->time << "\t|" | |
<< std::distance(first, next) << "====================== \n"; | |
//auto range = boost::make_iterator_range(first, next); | |
//process(filter_range.begin()); | |
//process(filter_range.end()); | |
auto filter_range = make_filter_range(by_band, first, next, [](const SatData& elem){return elem.sat_system != "GLONASS";}); | |
process(filter_range.begin(), filter_range.end()); | |
/*std::cout | |
<< "\n====================== BAND: " | |
<< first->sat_system << "\t|" | |
<< first->band << "\t|" | |
<< first->index << "\t|" | |
<< first->time << "\t|" | |
<< std::distance(first, next) << "====================== \n"; | |
process(first, next);*/ | |
first = next; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://stackoverflow.com/questions/71184389/where-order-by-using-boostmulti-index