Skip to content

Instantly share code, notes, and snippets.

@nekko1119
Last active December 1, 2015 19:09
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 nekko1119/62f645a02d2adfefd7fe to your computer and use it in GitHub Desktop.
Save nekko1119/62f645a02d2adfefd7fe to your computer and use it in GitHub Desktop.
rubyのgroup_byをC++で書いてみた
#include <vector>
#include <numeric>
#include <unordered_map>
#include <iterator>
#include <functional>
#include <type_traits>
#include <utility>
template <typename T, typename A>
std::string to_string(std::vector<T, A> const& v);
template <typename T>
struct get_value_type
{
using type = typename T::value_type;
};
template <typename T>
using remove_ref_cv = std::remove_reference_t<std::remove_cv_t<T>>;
template <typename C>
using value_type = typename std::conditional_t<std::is_array<C>::value, std::remove_extent<C>, get_value_type<C>>::type;
template <typename C, typename F>
auto group_by(C const& c, F f)
{
using val_t = remove_ref_cv<value_type<C>>;
using result_type = std::unordered_map<std::result_of_t<F(val_t)>, std::vector<val_t>>;
return std::accumulate(std::begin(c), std::end(c), result_type{}, [f = std::forward<F>(f)](auto&& acc, auto&& value) {
auto&& k = f(std::forward<decltype(value)>(value));
acc[k].emplace_back(std::forward<decltype(value)>(value));
return acc;
});
}
#include <iostream>
template <typename OStream, typename T, typename A>
OStream& operator<<(OStream& os, std::vector<T, A> const& v)
{
os << "[";
bool first{true};
for (auto const& x : v) {
if (!std::exchange(first, false)) {
os << ", ";
}
os << x;
}
os << "]";
return os;
}
template <typename OStream, typename K, typename V, typename H, typename P, typename A>
OStream& operator<<(OStream& os, std::unordered_map<K, V, H, P, A> const& m)
{
os << "{";
bool first{true};
for (auto const& p : m) {
if (!std::exchange(first, false)) {
os << ", ";
}
os << p.first << "=>" << p.second;
}
os << "}";
return os;
}
int main()
{
//int v[] = {3, 5, 1, 4, 2, 0}; // でも動く
std::vector<int> v = {3, 5, 1, 4, 2, 0};
auto result = group_by(v, [](auto&& x) { return x % 3; });
std::cout << result << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment