如何对列表执行GroupBy Sum查询?

时间:2018-09-03 09:08:37

标签: c++ list c++11 group-by aggregate

背景

我尽可能与C#.Net + LINQ合作,并为参与的项目尝试C ++开发。当然,我完全意识到C#和C ++是两个不同的世界。

问题

我有一个std::list<T>,其中T是如下结构:

struct SomeStruct{
    int id;
    int rate;
    int value;
};

我需要得到rate的分组结果和value的总和。如何在此列表上执行GroupBy Sum聚合功能?

示例:

SomeStruct s1;
SomeStruct s2;
SomeStruct s3;

s1.id=1;
s1.rate=5;
s1.value=100;

s2.id=2;
s2.rate=10;
s2.value=50;

s3.id=3;
s3.rate=10;
s3.value=200;

std::list<SomeStruct> myList;
myList.push_front(s1);
myList.push_front(s2);
myList.push_front(s3);

使用这些输入,我想获得以下输出:

rate|value
----|-----
   5|  100
  10|  250

我发现了一些有前途的库,例如CINQcppitertools。但是由于缺乏足够的知识,我无法完全理解。如果有人引导我朝正确的方向前进,那真是太好了,我乐于学习新事物。

1 个答案:

答案 0 :(得分:1)

计算按组求和相对简单:

using sum_type = int; // but maybe you want a larger type
auto num_groups = max_rate + 1;
std::vector<sum_type> rate_sums(num_groups); // this is initialized to 0
for(const auto& s : myList) {
    rate_sums[s.rate] += s.value;
}

这是当rate的值在0max_rate之内并且max_rate相对于myList.size()不太大时;否则,内存使用可能会过多(并且初始化向量将有一些开销)。

如果rate值相对于myList.size()散布在较大的范围内,请考虑使用std::unoredered_map代替std::vector)。

上面的代码也可以并行化。使其并行化的方式取决于您的硬件,并且有各种各样的库可以帮助您做到这一点。在C ++ 20中,可能会有language facilities for parallelization

但是请记住,链接列表的处理速度相当慢,因为您必须取消引用任意地址才能从一个元素到另一个元素。如果您可以将输入输入为std::vector或纯数组,那将更快。如果不能,那么并行化可能毫无用处。