On 08/14/2015 05:12 AM, H. S. Teoh via Digitalmars-d-learn wrote:
On Fri, Aug 14, 2015 at 02:42:26AM +0000, Laeeth Isharc via Digitalmars-d-learn
wrote:
I have a range that is an array of structs. I would like to iterate
through the range, calling a function with the prior k items in the
range up to that point and storing the result of the function in a new
range/array.
what's the best way to do this? for low fixed k I could use zip with
staggered slices (s[3..$],s[2..$-1],s[1..$-2],s[0..$-3]) and then map.
I can't think of how to do it elegantly.
any thoughts?
Maybe something like this?
import std.algorithm;
import std.stdio;
import std.range;
auto slidingWindow(R)(R range, int k) {
return iota(k).map!(i => range.save.drop(i))
.array
.transposed;
}
void main() {
auto data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
writeln(data.slidingWindow(3));
}
To apply the function to each slice, just write:
data.slidingWindow(k).map!myFunc ...
I didn't figure out how to eliminate the short slices toward the end,
import std.algorithm;
import std.stdio;
import std.range;
auto transp(RoR)(RoR ror){
static struct Transp{
typeof(transposed(ror)) orig;
alias orig this;
@property bool empty(){
return orig.tupleof[0].any!(a=>a.empty);
}
}
return Transp(transposed(ror));
}
auto slidingWindow(R)(R range, int k) {
return iota(k).map!(i => range.save.drop(i)).array.transp;
}
void main() {
auto data = iota(1,11).array;
writeln(data.slidingWindow(3));
}
:o)
but all you need to do is to somehow drop the last (k-1) elements from
the range returned by slidingWindow.