[Issue 13865] New: std.range.rangeSplit
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Mon Dec 15 05:19:38 PST 2014
https://issues.dlang.org/show_bug.cgi?id=13865
Issue ID: 13865
Summary: std.range.rangeSplit
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: enhancement
Priority: P1
Component: Phobos
Assignee: nobody at puremagic.com
Reporter: bearophile_hugs at eml.cc
I suggest to add to Phobos a range similar to the "tee" function of the Python
itertools:
https://docs.python.org/2/library/itertools.html#itertools.tee
http://code.activestate.com/recipes/305588-simple-example-to-show-off-itertoolstee/
http://discontinuously.com/2012/06/inside-python-tee/
- - - - - - - -
The Python description:
itertools.tee(iterable[, n=2])
Return n independent iterators from a single iterable. Equivalent to:
def tee(iterable, n=2):
it = iter(iterable)
deques = [collections.deque() for i in range(n)]
def gen(mydeque):
while True:
if not mydeque: # when the local deque is empty
newval = next(it) # fetch a new value and
for d in deques: # load it to all the deques
d.append(newval)
yield mydeque.popleft()
return tuple(gen(d) for d in deques)
- - - - - - - -
A bare-bones implementation in D (this is not meant to be the efficient and
reliable implementation for Phobos):
import std.traits: hasIndirections;
import std.concurrency: Generator, yield;
import std.range: ElementType;
import std.algorithm: map;
import std.array: array;
import queue_usage2: GrowableCircularQueue;
auto rangeDup(R)(R seq, in uint n=2) {
alias T = ElementType!R;
auto deques = new GrowableCircularQueue!T[n];
auto gen(ref GrowableCircularQueue!T mydeque) {
return new Generator!T({
while (true) {
if (mydeque.empty) {
auto newVal = seq.front;
seq.popFront;
foreach (ref d; deques)
d.push(newVal);
}
yield(mydeque.pop);
}
});
}
return deques.map!gen.array;
}
// An usage example:
enum sternBrocot = () => new Generator!uint({
GrowableCircularQueue!uint sb;
sb.push(1u);
sb.push(1u);
while (true) {
sb.push(sb[0] + sb[1]);
sb.push(sb[1]);
yield(sb.pop);
}
});
void main() {
import std.stdio, std.range, std.algorithm, std.numeric;
auto ss = rangeDup(sternBrocot());
ss[1].popFront;
assert(zip(ss[0], ss[1]).take(1_000).all!(t => gcd(t[0], t[1]) == 1));
}
--
More information about the Digitalmars-d-bugs
mailing list