Combining infinite ranges
bearophile
bearophileHUGS at lycos.com
Wed Jun 2 17:24:43 PDT 2010
Andrei Alexandrescu:
> iota(n, n.max) is close. Well, it's not infinite, but cycle(iota(n,
> n.max)) is. Probably a version using BigInt would be most sensible.
An enumerate() too can be useful (not much tested yet):
import std.range: isForwardRange, hasLength, isBidirectionalRange, ElementType;
import std.typecons: Tuple;
import std.array: front, back, empty, popFront, popBack;
/// ...
struct Enumerate(R) if (isForwardRange!R) {
alias Tuple!(size_t, "index", ElementType!R, "item") TPair;
R _range;
size_t _index;
static if (isBidirectionalRange!R && hasLength!R)
immutable size_t _originalEnd;
this(R input) {
_range = input;
static if (isBidirectionalRange!R && hasLength!R)
_originalEnd = _range.length - 1;
}
/// Range primitive implementations.
ref TPair front() {
return TPair(_index, _range.front());
}
/// Ditto
bool empty() {
return _range.empty();
}
/// Ditto
void popFront() {
_range.popFront();
_index++;
}
static if (isBidirectionalRange!R && hasLength!R) {
/// Ditto
ref TPair back() {
return TPair(_originalEnd + _index, _range.back());
}
}
static if (isBidirectionalRange!R && hasLength!R) {
/// Ditto
void popBack() {
_range.popBack();
_index--;
}
}
static if (hasLength!R) {
/// Ditto
@property auto length() {
return _range.length;
}
}
}
/// Ditto
Enumerate!R enumerate(R)(R input) if (isForwardRange!R) {
return Enumerate!R(input);
}
import std.stdio: write, writeln;
void main() {
string[] arr = ["y", "n", "y", "n", "y"];
foreach (el; enumerate(arr))
write(el, " ");
writeln("\n");
foreach_reverse (el; enumerate(arr))
write(el, " ");
writeln("\n");
}
I don't know if a reverse iteration on an enumerate can be useful.
-----------------------
I have used that to try to implement in D2 this Python code:
>>> arr = ["y", "n", "y", "n", "y"]
>>> [i for i,el in enumerate(arr) if el == "y"]
[0, 2, 4]
This is a basic D version, Appender not used:
import std.stdio: writeln;
void main() {
// input data
string[] arr = ["y", "n", "y", "n", "y"];
//
int[] indexes;
foreach (i, item; arr)
if (item == "y")
indexes ~= i;
writeln(indexes);
writeln();
}
-----------------------
This is a more functional quite bad-looking D2 version, that doesn't work (see http://d.puremagic.com/issues/show_bug.cgi?id=4264 ):
import std.stdio: writeln;
import std.algorithm: filter, array, map;
void main() {
// input data
string[] arr = ["y", "n", "y", "n", "y"];
auto r1 = filter!((p){ return p.item == "y"; })(enumerate(arr));
auto r2 = map!((p){ return p.index; })(r1);
writeln(array(r2));
}
Bye,
bearophile
More information about the Digitalmars-d
mailing list