Skip to content

Instantly share code, notes, and snippets.

@mwhittaker
Last active December 14, 2016 18:28
Show Gist options
  • Save mwhittaker/4049ce77e6c1c6167c1e8a18fa337304 to your computer and use it in GitHub Desktop.
Save mwhittaker/4049ce77e6c1c6167c1e8a18fa337304 to your computer and use it in GitHub Desktop.
range-v3 examples
#include <iostream>
#include <map>
#include <tuple>
#include <utility>
#include <vector>
#include "range/v3/all.hpp"
using namespace ranges;
using intint = std::tuple<int, int>;
int key(const intint& xy) { return std::get<0>(xy); }
template <typename L, typename R>
std::ostream& operator<<(std::ostream& out, const std::tuple<L, R>& xy) {
const L& x = std::get<0>(xy);
const R& y = std::get<1>(xy);
out << "(" << x << ", " << y << ")";
return out;
}
template <typename T>
void type(const T&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
class Join {
public:
auto operator()(const common_pair<intint, intint>& xy) {
return yield_from(view::all(newly_joined(xy)));
}
private:
const std::vector<std::tuple<intint, intint>>& newly_joined(
const common_pair<intint, intint>& xy) {
const intint& x = std::get<0>(xy);
const intint& y = std::get<1>(xy);
newly_joined_.clear();
if (key(x) != -1) {
left_[key(x)].push_back(x);
for (const intint& y : right_[key(x)]) {
newly_joined_.push_back({x, y});
}
}
if (key(y) != -1) {
right_[key(y)].push_back(y);
for (const intint& x : left_[key(y)]) {
newly_joined_.push_back({x, y});
}
}
return newly_joined_;
}
std::map<int, std::vector<intint>> left_;
std::map<int, std::vector<intint>> right_;
std::vector<std::tuple<intint, intint>> newly_joined_;
};
template <typename Rng1, typename Rng2>
auto join(const Rng1& xs, const Rng2& ys) {
auto negative_ones = view::generate([]() { return intint{-1, -1}; });
return view::zip(view::concat(xs, negative_ones),
view::concat(ys, negative_ones)) //
| view::take_while([](const auto& xy) {
auto x = std::get<0>(xy);
auto y = std::get<1>(xy);
return key(x) != -1 && key(y) != -1;
}) //
| view::for_each(Join());
}
int main() {
std::vector<intint> xs = {{0, 1}, {1, 2}, {2, 3}, {2, 4}, {3, 5}};
std::vector<intint> ys = {{1, 10}, {2, 20}, {3, 30},
{3, 40}, {5, 50}, {6, 60}};
for_each(join(xs, ys), [](const auto& t) { std::cout << t << std::endl; });
}
#include <iostream>
#include <tuple>
#include <utility>
#include "range/v3/all.hpp"
using namespace ranges;
using Tuple = std::tuple<int, char, bool>;
template <typename T>
void type(const T&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
std::ostream& operator<<(std::ostream& out, const Tuple& t) {
const auto& first = std::get<0>(t);
const auto& second = std::get<1>(t);
const auto& third = std::get<2>(t);
out << "(" << first << ", " << second << ", " << third << ")";
return out;
}
int main() {
std::vector<Tuple> db = {
{1, 'a', true}, {2, 'd', true}, {3, 'g', false},
{4, 'b', false}, {5, 'e', true}, {6, 'h', false},
{7, 'c', true}, {8, 'f', false}, {9, 'i', true},
};
// select
auto is_even = [](const auto& t) { return std::get<0>(t) % 2 == 0; };
auto is_odd = [](const auto& t) { return std::get<0>(t) % 2 == 1; };
auto evens = db | view::filter(is_even);
auto odds = db | view::filter(is_odd);
for_each(evens, [](const auto& t) { std::cout << t << std::endl; });
for_each(evens, [](const auto& t) { std::cout << t << std::endl; });
// project
auto first = [](const auto& t) { return std::get<0>(t); };
auto second = [](const auto& t) { return std::get<1>(t); };
auto third = [](const auto& t) { return std::get<2>(t); };
auto ints = db | view::transform(first);
auto chars = db | view::transform(second);
auto bools = db | view::transform(third);
std::cout << ints << std::endl;
std::cout << chars << std::endl;
std::cout << bools << std::endl;
// zip
auto zipped = view::zip(db, db);
for_each(zipped, [](const auto& t) {
type(t);
const auto& first = std::get<0>(t);
const auto& second = std::get<1>(t);
std::cout << "(" << first << ", " << second << ")" << std::endl;
});
// types
std::cout << std::endl;
std::cout << "evens:" << std::endl;
type(evens);
std::cout << "odds:" << std::endl;
type(odds);
std::cout << "ints:" << std::endl;
type(ints);
std::cout << "chars:" << std::endl;
type(chars);
std::cout << "bools:" << std::endl;
type(bools);
std::cout << "zipped:" << std::endl;
type(zipped);
}
#include <iostream>
#include <map>
#include <tuple>
#include <utility>
#include <vector>
#include "range/v3/all.hpp"
using namespace ranges;
using intint = std::tuple<int, int>;
int key(const intint& xy) { return std::get<0>(xy); }
template <typename L, typename R>
std::ostream& operator<<(std::ostream& out, const std::tuple<L, R>& xy) {
const L& x = std::get<0>(xy);
const R& y = std::get<1>(xy);
out << "(" << x << ", " << y << ")";
return out;
}
template <typename Rng1, typename Rng2>
auto join(const Rng1& xs, const Rng2& ys) {
return xs //
| view::for_each([&ys](const auto& x) {
auto joined = //
ys //
| view::filter(
[&x](const auto& y) { return key(y) == key(x); }) //
| view::transform(
[&x](const auto& y) { return std::make_tuple(x, y); });
return yield_from(joined);
});
}
int main() {
std::vector<intint> xs = {{0, 1}, {1, 2}, {2, 3}, {2, 4}, {3, 5}};
std::vector<intint> ys = {{1, 10}, {2, 20}, {3, 30},
{3, 40}, {5, 50}, {6, 60}};
for_each(join(xs, ys), [](const auto& t) { std::cout << t << std::endl; });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment