Forum Discussion
Rolling accumulation
Hi,
I have been trying various methods of a rolling accumultion or bucketiing; so buckets of 3 = {1..10} =
{ {1}, {1,2}, { 1,2,3}, { 2,3,4} , {3,4,5}, {4,5,6}, {5,,6.7}, { 6,7,8} , { 7,8,9}, { 8,9,10}
so there is always adding index and firstN / lastN as a table,
but i have these two methods with generate or transform;
let
alist = {1 .. 15},
window = 3,
bucket = List.Generate(
() => 1,
each _ <= List.Count(alist),
each _ + 1,
each if _ < 4 then List.Range(alist, 0, _) else List.Range(alist, _ - window, window)
)
in
bucket
let
alist = {1 .. 15},
window = 3,
pos = {1 .. List.Count(alist)},
bucket = List.Transform(
pos,
(x) => if x < 4 then List.Range(alist, 0, x) else List.Range(alist, x - window, window)
)
in
bucketa slightly efficient method seems to be to pad the list with zeros, so here 2 window - 1 ,
which removes the logical test but does meant the first is {0,0,1}
has anyone any other approaches using different functions? perhaps using custom comparer in
groupby ?
Richard
Dicken please try with:
let alist = {1 .. 15}, window = 3, pad = List.Repeat({0}, window - 1), // {0, 0} padded = List.Combine({pad, alist}), // {0,0,1,2,...,15} positions = {0 .. List.Count(alist) - 1}, // 0-based indices for final result buckets = List.Transform( positions, each List.Range(padded, _, window) // always take exactly 'window' items ) in bucketsDicken Another option could be with List.Accumulate:
let alist = {1 .. 15}, window = 3, buckets = List.Accumulate( {1 .. List.Count(alist)}, {}, (state, current) => state & { if current <= window then List.Range(alist, 0, current) else List.Range(alist, current - window, window) } ) in buckets
7 Replies
- pcoleySuper User
Dicken Another option could be with List.Accumulate:
let alist = {1 .. 15}, window = 3, buckets = List.Accumulate( {1 .. List.Count(alist)}, {}, (state, current) => state & { if current <= window then List.Range(alist, 0, current) else List.Range(alist, current - window, window) } ) in buckets- DickenPost Prodigy
especially like the accumulate version.
- pcoleySuper User
Dicken please try with:
let alist = {1 .. 15}, window = 3, pad = List.Repeat({0}, window - 1), // {0, 0} padded = List.Combine({pad, alist}), // {0,0,1,2,...,15} positions = {0 .. List.Count(alist) - 1}, // 0-based indices for final result buckets = List.Transform( positions, each List.Range(padded, _, window) // always take exactly 'window' items ) in buckets - pcoleySuper User
Dicken also you can try with List.Generate:
let alist = {1 .. 15}, windowSize = 3, result = List.Generate( () => [idx = 0, win = {}], each [idx] < List.Count(alist), each [ idx = [idx] + 1, win = if [idx] < windowSize then List.Range(alist, 0, [idx] + 1) else List.Range(alist, [idx] - windowSize + 1, windowSize) ], each [win] ) in result- DickenPost Prodigy
Thaanks all, that's enough to be going on with i shall go through them all.
- AlienSxSuper User
let lst = {1..15}, window = 3, fx = (i, s) => if i = window then List.Zip(s) else @ fx(i + 1, {List.Repeat({null}, i) & List.RemoveLastN(lst, i)} & s) in fx(0, {}) - slorinSuper User
Hi
Another solution= List.Transform(
{1..List.Count(alist)},
(i)=> List.Transform(
List.Numbers(List.Max({0, i-window}), window),
each alist{_}))
Stéphane