Forum Discussion
Dicken
Post Prodigy
5 months agoList.Generate, make behave like Accumulate or XL REDUCE
Hi, my staring point was this, i wanted to accumute fieds to a record; so i used; let
f = {List.Sum, List.Max, List.Average},
head = {"sum", "max", "avg"},
pos = {0, 1, 2},
...
- 5 months ago
and try this
let f = {List.Sum,List.Max, List.Average}, head = { "sum", "max", "avg"}, val = {2,3,1,5,2,1}, to= List.Generate(()=> [ i = 0, j = Record.AddField( [],head {i}, f{i}(val) ) ], (x)=> x[i] <= List.Count( head)-1, (x)=> [i = x[i] + 1, j = Record.AddField( [],head {i},f{i}(val)) ], (x)=>x[j]) in Record.Combine( to)
ronrsnfld
Super User
5 months agoYou can use List.Generate, but it seems cumbersome when what you want to do is accumulate results into a single record as List.Accumulate can do. List.Generate returns a List by design.
One method would be to wrap List.Generate inside List.Last
let
val = {12,21,34} ,
pos = {0,1,2},
head = {"a","b","c"},
res = List.Last(List.Generate(
()=>[idx=0, x=Record.AddField([],head{idx},val{idx})],
each [idx] < List.Count(head),
each [idx=[idx]+1, x=Record.AddField([x],head{idx},val{idx})],
each Record.Combine({[x]})))
in
res
Another method would be to return a List of Records and then combine them into a single record:
let
val = {12,21,34} ,
pos = {0,1,2},
head = {"a","b","c"},
res = Record.Combine(List.Generate(
()=>[idx=0, x=Record.AddField([],head{idx},val{idx})],
each [idx] < List.Count(head),
each [idx=[idx]+1, x=Record.AddField([],head{idx},val{idx})],
each [x]))
in
res
Please note that the most efficient method (within your constraints) would be by using List.Accumulate. Theoretically, Record.Combine(List.Generate(... should be more efficient than List.Last(List.Generate(... as one is only generating a single record for each "loop" in the former, and increasing numbers of records in the latter.