Thread overview
iterating through a range, operating on last few elements at a time
Aug 14, 2015
Laeeth Isharc
Aug 14, 2015
H. S. Teoh
Aug 14, 2015
Timon Gehr
Aug 14, 2015
Timon Gehr
Aug 15, 2015
Laeeth Isharc
August 14, 2015
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?
August 14, 2015
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, but all you need to do is to somehow drop the last (k-1) elements from the range returned by slidingWindow.


T

-- 
Today's society is one of specialization: as you grow, you learn more and more about less and less. Eventually, you know everything about nothing.
August 14, 2015
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.
>


August 14, 2015
On 08/14/2015 03:26 PM, Timon Gehr wrote:
> On 08/14/2015 05:12 AM, H. S. Teoh via Digitalmars-d-learn wrote:
>> ...
>>
>> I didn't figure out how to eliminate the short slices toward the end,
>
> ...
>
> :o)
> ...

Less hacky and less efficient:

auto slidingWindow(R)(R range, int k) {
    return iota(k).map!(i=>range.save.drop(i))
        .array.transposed.zip(range.save.drop(k-1)).map!(a=>a[0]);
}

August 15, 2015
On Friday, 14 August 2015 at 13:32:57 UTC, Timon Gehr wrote:
> On 08/14/2015 03:26 PM, Timon Gehr wrote:
>> On 08/14/2015 05:12 AM, H. S. Teoh via Digitalmars-d-learn wrote:
>>> ...
>>>
>>> I didn't figure out how to eliminate the short slices toward the end,
>>
>> ...
>>
>> :o)
>> ...
>
> Less hacky and less efficient:
>
> auto slidingWindow(R)(R range, int k) {
>     return iota(k).map!(i=>range.save.drop(i))
>         .array.transposed.zip(range.save.drop(k-1)).map!(a=>a[0]);
> }

Thanks v much HS and Timon.


Laeeth.