Как выполнить запрос GroupBy Sum к списку? - PullRequest
0 голосов
/ 03 сентября 2018

Фон

Я работал с 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

Я нашел несколько многообещающих библиотек, таких как CINQ и cppitertools . Но я не мог полностью понять, поскольку у меня нет достаточных знаний. Было бы замечательно, если бы кто-то направил меня в правильном направлении, я более чем готов изучать новые вещи.

1 Ответ

0 голосов
/ 03 сентября 2018

Вычисление суммы по группам относительно просто:

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 находятся в пределах 0 и max_rate, а max_rate не слишком велико относительно myList.size(); в противном случае использование памяти может быть чрезмерным (и у вас будут некоторые накладные расходы при инициализации вектора).

Если значения rate разбросаны по большому диапазону относительно myList.size(), рассмотрите возможность использования std::unoredered_map вместо std::vector).

Код выше также можно распараллелить. Способ его распараллеливания зависит от вашего аппаратного обеспечения, и для этого есть все виды библиотек. В C ++ 20 могут быть языковые средства для распараллеливания .

Помните, однако, что связанные списки работают довольно медленно, потому что вам нужно разыменовать произвольный адрес для перехода от одного элемента к другому. Если вы можете получить свой ввод в std::vector или в простом массиве, это будет быстрее; и если вы не можете, вероятно, бесполезно беспокоиться о распараллеливании.

...