Skip to main content
Showing results for 
Search instead for 
Did you mean: 

Microsoft is giving away 50,000 FREE Microsoft Certification exam vouchers. Get Fabric certified for FREE! Learn more

Reply

Cumulative list that re starts when a text value is encountered.


Using  list.Generate, and having the list start with and contain text ,   i have come up  with this 
but woudl be interested in other ways espcially if try could be avoided and replaced with a let  statement ; 

 

let alist = {"A",3,3,2,"a","b",3,3,4,4,"c",2,3,3} 
in
List.Generate( ()=> [ x = 0 , y = alist {0}   ,  z = y ] ,
each [x] < List.Count( alist),
each [ x = [x] + 1,   y = alist{x} ,    z =try [y] + y otherwise y ],
each [z] )

Ricahrd 

3 ACCEPTED SOLUTIONS

I would agree with the comments @lbendlin made to your original code. But if you want to try something different...

List.Generate( ()=> [ iteration=0, iterationType=Value.Is(alist{0}, Text.Type), lastText = 0, currentValue = alist{0} ], each [iteration] < List.Count(alist), each [ iteration = [iteration]+1, iterationType = Value.Is(alist{iteration}, Text.Type), lastText = if iterationType then iteration else [lastText], currentValue = if iterationType or iteration = lastText + 1 then alist{iteration} else [currentValue] + alist{iteration} ], each [currentValue] )




Did I answer your question? Mark my post as a solution!

Proud to be a Super User!





View solution in original post

Easy enough,

let Source = {"A",3,3,3,"a","b",2,3,4,3,2,"c",2,3,3,3} in List.Accumulate(Source, {}, (s,c) => s & {try List.Last(s)+c otherwise c})

ThxAlot_0-1745263067971.png



Expertise = List.Accumulate(


        {Days as from Today},


        {Skills and Knowledge},


        (Current, Everyday) => Current & Day.LeanAndPractise(Everyday)


)



View solution in original post

v-dineshya
Community Support
Community Support

Hi @Dicken ,

Thank you for reaching out to the Microsoft Community Forum.,

 

Your current method uses try to handle the switching between number accumulation and text resets, which maybe not as readable or clean as it could be.

Here’s an alternate version using let inside List.Generate to replace try, making the logic a bit cleaner and more explicit:

let
alist = {"A", 3, 3, 2, "a", "b", 3, 3, 4, 4, "c", 2, 3, 3},
result = List.Generate(
()=> [x = 0, acc = 0, y = alist{0}, z = if Value.Is(alist{0}, type number) then alist{0} else alist{0}],
each [x] < List.Count(alist),
each
let
nextX = [x] + 1,
nextY = alist{nextX},
isNumber = Value.Is(nextY, type number),
nextAcc = if isNumber then if Value.Is([y], type number) then [acc] + nextY else nextY else 0,
nextZ = if isNumber then nextAcc else nextY
in
[x = nextX, y = nextY, acc = if isNumber then nextAcc else 0, z = nextZ],
each [z]
)
in
result

Note: acc is the accumulator for numbers. Resets acc to 0 whenever a text is encountered. Uses Value.Is(..., type number) instead of try to test for numbers. This version avoids try entirely and leans into let for logic clarity.

 

If my response has resolved your query, please mark it as the Accepted Solution to assist others. Additionally, a 'Kudos' would be appreciated if you found my response helpful.

Thank you

View solution in original post

18 REPLIES 18

Hi @Dicken., I would agree with all the posts here but this is a different approach to this solution. I'll attach the images of the output and M code used. Thanks!

SundarRaj_0-1745314273951.png

SundarRaj_1-1745314352342.png

Here's the code:

let
Source = {"A",3,3,2,"a","b",3,3,4,4,"c",2,3,3},
Table = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Ignore),
Rename = Table.RenameColumns(Table,{{"Column1", "Sum"}}),
Grouped = Table.Group(Rename, {"Sum"}, {{"All", each _[Sum], Int64.Type}},GroupKind.Local,(x,y) => Number.From( y[Sum] is text )),
All = Table.TransformColumns(Grouped, {"All", each List.Select(_, each not (try Number.From(_))[HasError])}),
Sum = Table.TransformColumns(All,{"All", each List.Skip(List.Accumulate(_, {0}, (s,c) => s & {List.Last(s) + c}))}),
Lists = Table.TransformColumns(Sum,{"Sum", each {_}}),
Merged = List.Transform(Table.ToRows(Lists), each List.Combine(_)),
Combined = List.Combine(Merged)
in
Combined

 

Like the idea, 
Im' going ot have to study that, 
I've got the grouping, Im not greae on custom comparers; 
but 
= Table.Group(Source, {"Unit"}, {{"Count", each
[Unit] }}, 0 , (x,y)=> Number.From(Value.Is( y [Unit] ,type text ) ))

and then thought within the grouping use something similar such as ; 

let alist = {"a",2,3,3,"a","b",3,3}
in
List.Accumulate( alist, {} , (s,c)=>s & { try (List.Last(s)??0 ) + c otherwise c } ) 

but of coursse the above still uses try . 

Richard 

I'll leave it open as I would be 

Not sure what your ultimate goal is. If you want to avoid the try ... otherwise ... approach (why?)  then use Value.Is() to sense the value type.

v-dineshya
Community Support
Community Support

Hi @Dicken ,

Thank you for reaching out to the Microsoft Community Forum.,

 

Your current method uses try to handle the switching between number accumulation and text resets, which maybe not as readable or clean as it could be.

Here’s an alternate version using let inside List.Generate to replace try, making the logic a bit cleaner and more explicit:

let
alist = {"A", 3, 3, 2, "a", "b", 3, 3, 4, 4, "c", 2, 3, 3},
result = List.Generate(
()=> [x = 0, acc = 0, y = alist{0}, z = if Value.Is(alist{0}, type number) then alist{0} else alist{0}],
each [x] < List.Count(alist),
each
let
nextX = [x] + 1,
nextY = alist{nextX},
isNumber = Value.Is(nextY, type number),
nextAcc = if isNumber then if Value.Is([y], type number) then [acc] + nextY else nextY else 0,
nextZ = if isNumber then nextAcc else nextY
in
[x = nextX, y = nextY, acc = if isNumber then nextAcc else 0, z = nextZ],
each [z]
)
in
result

Note: acc is the accumulator for numbers. Resets acc to 0 whenever a text is encountered. Uses Value.Is(..., type number) instead of try to test for numbers. This version avoids try entirely and leans into let for logic clarity.

 

If my response has resolved your query, please mark it as the Accepted Solution to assist others. Additionally, a 'Kudos' would be appreciated if you found my response helpful.

Thank you

Easy enough,

let Source = {"A",3,3,3,"a","b",2,3,4,3,2,"c",2,3,3,3} in List.Accumulate(Source, {}, (s,c) => s & {try List.Last(s)+c otherwise c})

ThxAlot_0-1745263067971.png



Expertise = List.Accumulate(


        {Days as from Today},


        {Skills and Knowledge},


        (Current, Everyday) => Current & Day.LeanAndPractise(Everyday)


)



I did say using Generate not accumulate and NOT using try otherwise 

List.Generate( () => [x = 0, y = Source{0}], each [x] < lc, each [x = [x] + 1, y = if Value.Is(Source{x},type text) or Value.Is([y],type text) then Source{x} else [y] + Source{x}], each [y] )

avoiding the try...otherwise...  for no good reason :slightly_smiling_face:

yes, you did say that. But the solution from Sir @ThxAlot is much more elegant .  Apart from a small-ish bug when the list starts with a number  In that case you need to use

 

let Source = {"A",3,3,3,"a","b",2,3,4,3,2,"c",2,3,3,3} in List.Accumulate(Source, {}, (s,c) => s & {try (List.Last(s) ?? 0)+c otherwise c})

I would agree with the comments @lbendlin made to your original code. But if you want to try something different...

List.Generate( ()=> [ iteration=0, iterationType=Value.Is(alist{0}, Text.Type), lastText = 0, currentValue = alist{0} ], each [iteration] < List.Count(alist), each [ iteration = [iteration]+1, iterationType = Value.Is(alist{iteration}, Text.Type), lastText = if iterationType then iteration else [lastText], currentValue = if iterationType or iteration = lastText + 1 then alist{iteration} else [currentValue] + alist{iteration} ], each [currentValue] )




Did I answer your question? Mark my post as a solution!

Proud to be a Super User!





I really like this generate method , I have it in notepad and taking apart. 
Thanks. 

Richard. 

I think I have enough to be working on for now thank you for all responses. 
Richad. 

Shouldn't the result for row 4 be 8 ?

 

lbendlin_0-1745258060558.png

 



Try this, 
let alist = { "A",3,3,3,"a","b",2,3,4,3,2,"c",2,3,3,3}
in
List.Generate( ()=> [ x = 0 , y = alist{0} ] ,
each [x] < List.Count( alist) ,
each [ x = [x] + 1, y = try [y] + alist {x} otherwise
alist{x} ] ,
each [y] )

How long is your actual list? Are you concerned about performance or code size?

 

Obviuosly I'd like it as effecient as possible, but Im just interested in alternatvie approaches, 
List.accumulate can be easier, but Generate is generally more effecient . 

No, not really. 

then go with your actual code.  Maybe throw in a List.Buffer just for fun, and pull the list count out of the loop.

 

let alist = List.Buffer({"A", 3, 3, 3, "a", "b", 2, 3, 4, 3, 2, "c", 2, 3, 3, 3}), lc = List.Count(alist) in List.Generate( () => [x = 0, y = alist{0}], each [x] < lc, each [x = [x] + 1, y = try [y] + alist{x} otherwise alist{x}], each [y] )

 

 

Yes, I'm sure I'd got it working, will re check. 

Helpful resources

Announcements
PBIApril_Carousel

Power BI Monthly Update - April 2025

Check out the April 2025 Power BI update to learn about new features.

Notebook Gallery Carousel1

NEW! Community Notebooks Gallery

Explore and share Fabric Notebooks to boost Power BI insights in the new community notebooks gallery.

April2025 Carousel

Fabric Community Update - April 2025

Find out what's new and trending in the Fabric community.

Top Solution Authors
Top Kudoed Authors
Users online (4,862)
  • suparnababu8
  • mphillenga
  • technolog
  • mamo_ob
  • wdx223_Daniel
  • omatura
  • pankajnamekar25
  • ray_codex
  • Aala_Ali
  • Oleh116611
  • ev88lifestyle
  • BeaBF
  • SEMattis
  • mussaenda
  • nilendraFabric
  • zenisekd
  • vz99gifts
  • PetriBlaauw
  • PijushRoy
  • MonicaEme
  • dk_patriot
close