Skip to content

Instantly share code, notes, and snippets.

@winger
Created July 28, 2020 23:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save winger/1e86bdcb4f9c360ab57dbccfbe861818 to your computer and use it in GitHub Desktop.
Save winger/1e86bdcb4f9c360ab57dbccfbe861818 to your computer and use it in GitHub Desktop.
#pragma once
#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <string>
#include <variant>
using Key = std::string;
using Value = std::variant<std::string, double, bool>;
using Item = std::unordered_map<Key, Value>;
using Items = std::vector<Item>;
struct Group {
Key groupField;
Value groupValue;
std::vector<Item> items;
std::unordered_map<Key, Value> aggregatedValues;
};
using Groups = std::vector<Group>;
Groups groupBy(Items& items, const Key groupField, const std::vector<Key>& sumFields) {
std::unordered_map<Value, Group> groupMap;
for (Item& item : items) {
auto& group = groupMap[item[groupField]];
if (group.items.empty()) {
group.groupField = groupField;
group.groupValue = item[groupField];
group.aggregatedValues = item;
} else {
for (const auto& sumField : sumFields) {
std::get<double>(group.aggregatedValues[sumField]) += std::get<double>(item[sumField]);
}
}
}
std::vector<Group> groups;
groups.reserve(groupMap.size());
for (auto& kv : groupMap) {
groups.emplace_back(std::move(kv.second));
}
return groups;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment