Dowolna ilość kluczy, dowolna ilość grup.
Jedyne trzeba uważać aby nie sumować grochu z kapustą.
Kopiuj
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
struct cash
{
double count,price,amount;
cash(double count=0,double price=0):count(count),price(price),amount(count*price) {}
cash &operator+=(const cash &add)
{
count+=add.count;
price+=add.price;
amount+=add.amount;
return *this;
}
};
typedef vector<size_t> group;
typedef vector<string> params;
struct data
{
cash cs;
params pr;
};
typedef vector<data> datasource;
struct key
{
size_t parent;
string value;
key(size_t parent=0,const string &value=string()):parent(parent),value(value) {}
bool operator<(const key &k)const
{
if(parent<k.parent) return true;
if(parent>k.parent) return false;
return value<k.value;
}
};
struct idxcash
{
size_t idx;
cash sumary;
idxcash(size_t idx=0,const cash &sumary=cash()):idx(idx),sumary(sumary) {}
};
typedef map<key,idxcash> tree;
void maketree(tree &tr,const datasource &data,const group &grp)
{
tr.clear();
size_t idx=0;
key kk(0,"razem");
idxcash &top=tr[kk]=idxcash(++idx);
for(auto rec:data)
{
top.sumary+=rec.cs;
size_t parent=1;
for(size_t level=0;level<grp.size();++level)
{
idxcash &ics=tr[key(parent,rec.pr[grp[level]])];
if(!ics.idx) ics.idx=++idx;
ics.sumary+=rec.cs;
parent=ics.idx;
}
}
}
void printtree(ostream &xout,tree &tr,size_t level,size_t parent)
{
xout<<fixed;
tree::iterator begin=tr.lower_bound(key(parent));
tree::iterator end=tr.lower_bound(key(parent+1));
for(tree::iterator i=begin;i!=end;++i)
{
if(level>0) xout<<setw(level)<<' ';
const string &title=i->first.value;
xout<<title<<setw(20-level-title.size())<<' ';
xout<<setw(12)<<setprecision(2)<<i->second.sumary.count;
xout<<setw(12)<<setprecision(2)<<i->second.sumary.price;
xout<<setw(12)<<setprecision(2)<<i->second.sumary.amount;
xout<<endl;
printtree(xout,tr,level+3,i->second.idx);
}
}
void groupby(ostream &xout,const datasource &data,const group &grp)
{
tree tr;
maketree(tr,data,grp);
printtree(xout,tr,0,0);
xout<<"==============================="<<endl<<endl;
}
datasource bigdata
{
{cash(5,2),{"55","marchewka","kg","Asia"}},
{cash(3,5),{"55","sliwki","kg","Kasia"}},
{cash(3,100),{"67","buty","szt","Asia"}},
{cash(4,70),{"67","marki","szt","Kasia"}},
{cash(5,20),{"67","gumowiec","szt","Jola"}},
{cash(6,20),{"12","pasta","szt","Asia"}},
{cash(5,10),{"12","do","szt","Jola"}},
{cash(4,5),{"12","nosa","szt","Basia"}},
};
int main()
{
groupby(cout,bigdata,{2,0,3});
groupby(cout,bigdata,{0,2});
groupby(cout,bigdata,{2,0,1});
return 0;
}