Last active
April 18, 2016 23:31
-
-
Save Hackerpilot/d10880171ee92194087897fd02fe7379 to your computer and use it in GitHub Desktop.
Route an input range to an output range based on function return value
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.range.primitives : isInputRange, isOutputRange, ElementType; | |
import std.meta : ApplyLeft, allSatisfy, staticMap; | |
import std.functional : unaryFun; | |
import std.traits : Unqual; | |
/** | |
* Copy values from an input range to one of several output ranges based | |
* on a routing function. | |
* | |
* The function must return an integer between 0 and the number of outputs. | |
* | |
* Params: | |
* Decider = the decision function | |
* I = the input range type | |
* O = the output range types | |
* input = the input range | |
* outputs = the output ranges | |
*/ | |
void route(alias Decider, I, O...)(auto ref I input, auto ref O outputs) | |
if (isInputRange!(Unqual!I) && is(typeof(unaryFun!Decider)) | |
&& allSatisfy!(ApplyLeft!(isOutputRange, ElementType!(Unqual!I), | |
staticMap!(Unqual, O)))) | |
{ | |
import std.range.primitives : put; | |
alias _f = unaryFun!Decider; | |
foreach (i; input) | |
{ | |
immutable size_t index = _f(i); | |
assert(index < O.length, "Index returned by decision function out of range"); | |
foreach (Index, _; O) | |
if (Index == index) | |
outputs[Index].put(i); | |
} | |
} | |
/// | |
unittest | |
{ | |
import std.array : appender; | |
import std.algorithm.comparison : equal; | |
int[] arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; | |
auto r1 = appender!(int[]); | |
auto r2 = appender!(int[]); | |
auto r3 = appender!(int[]); | |
arr.route!(a => a % 3)(r1, r2, r3); | |
assert(equal(r1.data, [0, 3, 6, 9, 12])); | |
assert(equal(r2.data, [1, 4, 7, 10])); | |
assert(equal(r3.data, [2, 5, 8, 11])); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment