Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
August 14, 2015 iterating through a range, operating on last few elements at a time | ||||
---|---|---|---|---|
| ||||
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 Re: iterating through a range, operating on last few elements at a time | ||||
---|---|---|---|---|
| ||||
Posted in reply to Laeeth Isharc | 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 Re: iterating through a range, operating on last few elements at a time | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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 Re: iterating through a range, operating on last few elements at a time | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | 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 Re: iterating through a range, operating on last few elements at a time | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | 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.
|
Copyright © 1999-2021 by the D Language Foundation