Forum Discussion
Best Practice: List.Generate in M
- 9 years ago
Hi Kealkil4
It is hard to give you an answer that 100% fits your needs, and it is better if you can provide a little bit more detailed description of your algorythm - because best practice is depends on what you really want to do with your tables.
In the most cases the main pitfall of List.Generate is the correct use of second parameter, which is used to check the condition to stop/continue list generation. The pitfall (not obvious) is that this parameter executes BEFORE the third step is actually performing.
You can consider the next steps of evaluation:
- first argument evaluated
- second parameter checks the evaluation result of the previuos step.
- If the result of step 2 is true, then record value (evaluated step 1) is used as output result, or it could be passed to the 4th parameter which generates the resulting list element. If the result of step 2 is false, then function stops.
- then (at last) the third argument evaluated
- GOTO step 2
You can see that List.Generate uses the next algorythm:
A = Evaluate arg1 Do While <arg2 condition> list element = A or arg4 A = evaluate arg3 Loop
You can check example here:
let sTable= #table({"1"},{{"a"},{"b"},{"c"}}), Source = List.Generate(()=> [ x = 0, y=Table.RowCount(sTable),z=sTable{x}[1]] , each [x] < [y] , each [x = [x]+1, y=[y], z=sTable{x}[1]]), Custom1 = Table.FromRecords(Source) in Custom1where I generate a simple table with one column, then it generate a list of records, each record has a row index (base 0), number of rows in the source table, and values from this table.
Actualy you can chose, either to use row number to check or use any other check as the 2nd argument, but to avoid errors you should consider List.Generate evaluation algorythm
Hi Kealkil4
It is hard to give you an answer that 100% fits your needs, and it is better if you can provide a little bit more detailed description of your algorythm - because best practice is depends on what you really want to do with your tables.
In the most cases the main pitfall of List.Generate is the correct use of second parameter, which is used to check the condition to stop/continue list generation. The pitfall (not obvious) is that this parameter executes BEFORE the third step is actually performing.
You can consider the next steps of evaluation:
- first argument evaluated
- second parameter checks the evaluation result of the previuos step.
- If the result of step 2 is true, then record value (evaluated step 1) is used as output result, or it could be passed to the 4th parameter which generates the resulting list element. If the result of step 2 is false, then function stops.
- then (at last) the third argument evaluated
- GOTO step 2
You can see that List.Generate uses the next algorythm:
A = Evaluate arg1 Do While <arg2 condition> list element = A or arg4 A = evaluate arg3 Loop
You can check example here:
let
sTable= #table({"1"},{{"a"},{"b"},{"c"}}),
Source = List.Generate(()=> [ x = 0, y=Table.RowCount(sTable),z=sTable{x}[1]] , each [x] < [y] , each [x = [x]+1, y=[y], z=sTable{x}[1]]),
Custom1 = Table.FromRecords(Source)
in
Custom1where I generate a simple table with one column, then it generate a list of records, each record has a row index (base 0), number of rows in the source table, and values from this table.
Actualy you can chose, either to use row number to check or use any other check as the 2nd argument, but to avoid errors you should consider List.Generate evaluation algorythm
In my view "try ... otherwise" (and even "List.Generate") should be avoided whenever possible.
But without detailed information it is impossible to provide a specifc answer.