SCANBYROW

SCANBYROW(initial_value,array,fn)
initial_value
first value for calculation; can be blank, same as SCAN
array
array to calculate over
fn
a 2-parameter LAMBDA, i.e. LAMBDA(acc,val,acc+val)

Performs a SCAN(initial_value,row,fn) on each row of array.

tboulden

Board Regular
Joined
Jan 14, 2021
Messages
73
Office Version
  1. 365
Platform
  1. Windows
Performs a SCAN(initial_value,row,fn) on each row of array. Corresponding SCANBYCOL is also shown.

BYROW/BYCOL are limited in returning a single value per row/column respectively, whereas SCAN returns an array of the same dimensions as the array being SCANned. We can overcome this limitation by thunk-ing the array result: this is essentially wrapping with a LAMBDA with no parameters, i.e. LAMBDA(x). Then to get the thunked x out, we do LAMBDA(x)() = x.

Excel Formula:
=LAMBDA(initial_value,array,fn,
    LET(
        rows_,ROWS(array),
        cols_,COLUMNS(array),
        row_thunks,
            BYROW(array,
                LAMBDA(row_,
                    LAMBDA(SCAN(initial_value,row_,fn))
                )
            ),
        MAKEARRAY(rows_,cols_,
            LAMBDA(i,j,
                INDEX(
                    INDEX(row_thunks,i,1)(),
                    1,
                    j
                )
            )
        )
    )
)

LAMBDA_SCANBY.xlsx
ABCDEFGHIJ
1
21234
35678
49101112
513141516
6
7=SCANBYROW(,$B$2#, LAMBDA(acc,val,acc+val))=SCANBYROW(10,$B$2#, LAMBDA(acc,val,acc+val))
8
91361011131620
10511182615212836
11919304219294052
121327425823375268
13
14=SCANBYCOL(,$B$2#, LAMBDA(acc,val,acc+val))=SCANBYCOL(10,$B$2#, LAMBDA(acc,val,acc+val))
15
16123411121314
1768101216182022
181518212425283134
192832364038424650
Sheet1
Cell Formulas
RangeFormula
B2:E5B2=SEQUENCE(4,4)
B7,G14,B14,G7B7=FORMULATEXT(B9)
B9:E12B9=SCANBYROW(,$B$2#, LAMBDA(acc,val,acc+val))
G9:J12G9=SCANBYROW(10,$B$2#, LAMBDA(acc,val,acc+val))
B16:E19B16=SCANBYCOL(,$B$2#, LAMBDA(acc,val,acc+val))
G16:J19G16=SCANBYCOL(10,$B$2#, LAMBDA(acc,val,acc+val))
Dynamic array formulas.
 
Upvote 1
SCANBYCOL
Excel Formula:
=LAMBDA(initial_value,array,fn,
    LET(
        rows_,ROWS(array),
        cols_,COLUMNS(array),
        col_thunks,
            BYCOL(array,
                LAMBDA(col_,
                    LAMBDA(SCAN(initial_value,col_,fn))
                )
            ),
        MAKEARRAY(rows_,cols_,
            LAMBDA(i,j,
                INDEX(
                    INDEX(col_thunks,1,j)(),
                    i,
                    1
                )
            )
        )
    )
)
 
Additional examples:
LAMBDA_SCANBY.xlsx
ABCDEFGHIJ
1
2ABCD
3EFGH
4IJKL
5MNOP
6
7=SCANBYROW(,$B$2#, LAMBDA(acc,val,acc&val))=SCANBYROW("Test_",$B$2#, LAMBDA(acc,val,acc&val))
8
9AABABCABCDTest_ATest_ABTest_ABCTest_ABCD
10EEFEFGEFGHTest_ETest_EFTest_EFGTest_EFGH
11IIJIJKIJKLTest_ITest_IJTest_IJKTest_IJKL
12MMNMNOMNOPTest_MTest_MNTest_MNOTest_MNOP
13
14=SCANBYCOL(,$B$2#, LAMBDA(acc,val,val&acc))=SCANBYCOL("_Test",$B$2#, LAMBDA(acc,val,val&acc))
15
16ABCDA_TestB_TestC_TestD_Test
17EAFBGCHDEA_TestFB_TestGC_TestHD_Test
18IEAJFBKGCLHDIEA_TestJFB_TestKGC_TestLHD_Test
19MIEANJFBOKGCPLHDMIEA_TestNJFB_TestOKGC_TestPLHD_Test
Alpha
Cell Formulas
RangeFormula
B2:E5B2=CHAR(SEQUENCE(4,4,65,1))
B7,G14,B14,G7B7=FORMULATEXT(B9)
B9:E12B9=SCANBYROW(,$B$2#, LAMBDA(acc,val,acc&val))
G9:J12G9=SCANBYROW("Test_",$B$2#, LAMBDA(acc,val,acc&val))
B16:E19B16=SCANBYCOL(,$B$2#, LAMBDA(acc,val,val&acc))
G16:J19G16=SCANBYCOL("_Test",$B$2#, LAMBDA(acc,val,val&acc))
Dynamic array formulas.


Functions below fairly self-explanatory, IDENTITY = LAMBDA(x,x), ADDONE = LAMBDA(x,x+1), etc.

LAMBDA_SCANBY.xlsx
ABCDEFGHI
1COMPOSE := LAMBDA(f,g,LAMBDA(x,g(f(x))))
2
3CHOOSE functions array
45636IDENTITYADDONEMINUSTHREETIMESTWO
524618MINUSTHREETIMESTWOADDTWOTIMESTHREE
67785ADDTWOIDENTITYADDONEMINUSTHREE
715121224TIMESTHREEMINUSTHREEIDENTITYTIMESTWO
8
9Composed across the row
10IDENTITYADDONE(IDENTITY)MINUSTHREE(ADDONE(IDENTITY))TIMESTWO(MINUSTHREE(ADDONE(IDENTITY)))
11MINUSTHREETIMESTWO(MINUSTHREE)ADDTWO(TIMESTWO(MINUSTHREE))TIMESTHREE(ADDTWO(TIMESTWO(MINUSTHREE)))
12ADDTWOIDENTITY(ADDTWO)ADDONE(IDENTITY(ADDTWO))MINUSTHREE(ADDONE(IDENTITY(ADDTWO)))
13TIMESTHREEMINUSTHREE(TIMESTHREE)IDENTITY(MINUSTHREE(TIMESTHREE))TIMESTWO(IDENTITY(MINUSTHREE(TIMESTHREE)))
14
15Composed down the column
1656210IDENTITYADDONEMINUSTHREETIMESTWO
17212430MINUSTHREE(IDENTITY)TIMESTWO(ADDONE)ADDTWO(MINUSTHREE)TIMESTHREE(TIMESTWO)
18412527ADDTWO(MINUSTHREE(IDENTITY))IDENTITY(TIMESTWO(ADDONE))ADDONE(ADDTWO(MINUSTHREE))MINUSTHREE(TIMESTHREE(TIMESTWO))
19129554TIMESTHREE(ADDTWO(MINUSTHREE(IDENTITY)))MINUSTHREE(IDENTITY(TIMESTWO(ADDONE)))IDENTITY(ADDONE(ADDTWO(MINUSTHREE)))TIMESTWO(MINUSTHREE(TIMESTHREE(TIMESTWO)))
COMPOSE
Cell Formulas
RangeFormula
A4:D7A4=MAP(SCANBYROW(,CHOOSE({1,2,3,4;3,4,5,6;5,1,2,3;6,3,1,4},IDENTITY,ADDONE,MINUSTHREE,TIMESTWO,ADDTWO,TIMESTHREE),COMPOSE),LAMBDA(fn,fn(5)))
F4:I7F4=CHOOSE({1,2,3,4;3,4,5,6;5,1,2,3;6,3,1,4},"IDENTITY","ADDONE","MINUSTHREE","TIMESTWO","ADDTWO","TIMESTHREE")
F10:I13F10=SCANBYROW(,F4#,LAMBDA(acc,fn,fn&"("&acc&")"))
A16:D19A16=MAP(SCANBYCOL(,CHOOSE({1,2,3,4;3,4,5,6;5,1,2,3;6,3,1,4},IDENTITY,ADDONE,MINUSTHREE,TIMESTWO,ADDTWO,TIMESTHREE),COMPOSE),LAMBDA(fn,fn(5)))
F16:I19F16=SCANBYCOL(,F4#,LAMBDA(acc,fn,fn&"("&acc&")"))
Dynamic array formulas.
 
Hi tboulden,

These functions are absolutely amazing and useful and thanks for sharing. However, I've got an error from one of the excamples above when I copied it into a speadsheet. In fact, I first put the SCANBYROW, SCANBYCOL, COMPOSE functions into the name manager. Then I got this below:

SCANBYROW+SCANBYCOL.xlsx
ABCDEFGHI
1COMPOSE := LAMBDA(f,g,LAMBDA(x,g(f(x))))
2
3CHOOSE functions array
4#VALUE!#VALUE!#VALUE!#VALUE!IDENTITYADDONEMINUSTHREETIMESTWO
5#VALUE!#VALUE!#VALUE!#VALUE!MINUSTHREETIMESTWOADDTWOTIMESTHREE
6#VALUE!#VALUE!#VALUE!#VALUE!ADDTWOIDENTITYADDONEMINUSTHREE
7#VALUE!#VALUE!#VALUE!#VALUE!TIMESTHREEMINUSTHREEIDENTITYTIMESTWO
8
9Composed across the row
10IDENTITYADDONE(IDENTITY)MINUSTHREE(ADDONE(IDENTITY))TIMESTWO(MINUSTHREE(ADDONE(IDENTITY)))
11MINUSTHREETIMESTWO(MINUSTHREE)ADDTWO(TIMESTWO(MINUSTHREE))TIMESTHREE(ADDTWO(TIMESTWO(MINUSTHREE)))
12ADDTWOIDENTITY(ADDTWO)ADDONE(IDENTITY(ADDTWO))MINUSTHREE(ADDONE(IDENTITY(ADDTWO)))
13TIMESTHREEMINUSTHREE(TIMESTHREE)IDENTITY(MINUSTHREE(TIMESTHREE))TIMESTWO(IDENTITY(MINUSTHREE(TIMESTHREE)))
14
15Composed down the column
16#NAME?#NAME?#NAME?#NAME?IDENTITYTIMESTWOIDENTITYIDENTITY
17#NAME?#NAME?#NAME?#NAME?MINUSTHREE(IDENTITY)TIMESTWO(ADDONE)ADDTWO(MINUSTHREE)TIMESTHREE(TIMESTWO)
18#NAME?#NAME?#NAME?#NAME?ADDTWO(MINUSTHREE(IDENTITY))IDENTITY(TIMESTWO(ADDONE))ADDONE(ADDTWO(MINUSTHREE))MINUSTHREE(TIMESTHREE(TIMESTWO))
19#NAME?#NAME?#NAME?#NAME?TIMESTHREE(ADDTWO(MINUSTHREE(IDENTITY)))MINUSTHREE(IDENTITY(TIMESTWO(ADDONE)))IDENTITY(ADDONE(ADDTWO(MINUSTHREE)))TIMESTWO(MINUSTHREE(TIMESTHREE(TIMESTWO)))
Sheet2
Cell Formulas
RangeFormula
A4:D7A4=MAP(SCANBYROW(,CHOOSE({1,2,3,4;3,4,5,6;5,1,2,3;6,3,1,4},IDENTITY,ADDONE,MINUSTHREE,TIMESTWO,ADDTWO,TIMESTHREE),COMPOSE),LAMBDA(fn,fn(5)))
F4:I7F4=CHOOSE({1,2,3,4;3,4,5,6;5,1,2,3;6,3,1,4},"IDENTITY","ADDONE","MINUSTHREE","TIMESTWO","ADDTWO","TIMESTHREE")
F10:I13F10=SCANBYROW(,F4#,LAMBDA(acc,fn,fn&"("&acc&")"))
A16:D19A16=MAP(SCANBYCOL(,CHOOSE({1,2,3,4;3,4,5,6;5,1,2,3;6,3,1,4},IDENTITY,ADDONE,MINUSTHREE,TIMESTWO,ADDTWO,TIMESTHREE),COMPOSE),LAMBDA(fn,fn(5)))
F16:I19F16=SCANBYCOL(,F4#,LAMBDA(acc,fn,fn&"("&acc&")"))
Dynamic array formulas.


Could you please help debug the #VALUE! error? Meanwhile, I didn't quite understand the COMPOSE function "=LAMBDA(f,g,LAMBDA(x,g(f(x))))" and how it works. May I expect you to shed some light on it?

Thank you so much in advance.
 
Could you please help debug the #VALUE! error? Meanwhile, I didn't quite understand the COMPOSE function "=LAMBDA(f,g,LAMBDA(x,g(f(x))))" and how it works. May I expect you to shed some light on it?

Thank you so much in advance.
Hi vincethesun! Did you also put IDENTITY, ADDONE, etc. in the Name Manager?

As for COMPOSE, this is a common way to create a "new" function from two existing functions; you could define a function in the Name Manager that is the combination of the two existing functions but this is 1) redundant to a certain degree and 2) time-consuming if you need to compose many different functions in different order. Function composition such as COMPOSE turns a set of a few simple functions into a tool-kit for more complex functions for a low amount of effort. Google for "function composition" and many math or comp sci results can help explain with more detail.

Hope this help!
 
Thanks tboulden. I did omit to put one of them in the Name Manager. Now it works perfectly.

Again, the LAMBDA-based UDFs and examples you shared are mind-blowing and incredibly powerful together with their simplicity and elegance. I'm litterally reshaping my understanding of Excel capacities with the amazing LAMBDA function thanks to you. Cheers and bravo!
 
These are amazing designs, but…
…when comes to combining lambda helper techniques, thunks , nested lambdas, time complexity should be taken in consideration because can increase exponentially, decreasing the performance also exponentially.
Believe it or not, 3 hours compared with 1 second, this is the proportion.
From the beginning , 3 y ago, me and tboulden were comparing formulas here : ASCAN
Lessons learned after all these years of Excel real life tasks ; the golden rules of lambda helper environment:

- There is always a more efficient solution. And the best one is the one that can work without them at all.
- Always test your solutions for time complexity, predicting the largest data set for your scenario.
- If not too many repetitive tasks, minimalistic formulas can be a lot faster than a custom made lambda based on the same concept design.
An extra argument or a single tiny extra not needed calculation can slow down the entire algorithm drastically. (an extra IF doing nothing in a lambda, for a specific task, slowed down an algorithm 3 times)
- Instead of complex and slow, better simple and fast. 😉

On this case, SCAN already scans, by its default nature, doesn't need to spill or shrink or pass values, so the only thing we need to scan byrow is to reset the initial value at the beginning of each row.
It's like a SCAN but with a "manual" shift transmission, still as fast as SCAN
I've always used this concept ASCAN for this kind of tasks since 2021 in endless scenarios as task adapted formulas.
Latest was for Excel Off The Grid. Advanced Excel Functions | BYROW vs MAP vs SCAN vs REDUCE | Excel Off The Grid
Anyhow , whomever needs lambdas this is how they look:
I will publish, hopefully, at ASCAN, if anybody needs, lambda that does it all, regular scan row/clm direction, or/and by each row/clm. Or CSCAN lambdas , Consecutive conditional scanning , pair, triple or n elements scanning, for vectors or arrays.

SCANR(v₀, ▦, λ) Scan ByRow

Excel Formula:
=LAMBDA(v₀, ▦, λ,
    LET(
        c, COLUMNS(▦),
        SCAN(0, SEQUENCE(ROWS(▦), c), LAMBDA(v, i, LET(m, MOD(i - 1, c), q, QUOTIENT(i - 1, c) + 1, x, INDEX(▦, q, m + 1), IF(m, λ(v, x), IF(ISOMITTED(v₀), x, λ(v₀, x))))))
    )
)

SCANC(v₀, ▦, λ) Scan ByCol (scan and scanr are double transpose compatible)
Excel Formula:
=LAMBDA(v₀,▦,λ,TRANSPOSE(SCANR(v₀,TRANSPOSE(▦),λ)))

v₀: initial value ; ▦: array ; λ: fn(x,y) function of 2 var like in regular SCAN
Some other timing results and more tests:
SCANBY.xlsx
ABCDEFGHIJKLMNOPQRSTUVWXYZAA
1
2 =SCANBYROW(0,B4#,SUM)n rowstiming results
3=SEQUENCE(1000000,10)=SCANR(0,B4#,SUM)seq(n,10)SCANBYROWSCANR
4123456789101361015212836455510,00016m27s0s
5111213141516171819201123365065819811613515520,00001h16m32s1s
6212223242526272829302143669011514116819622525530,00003h18m48s1s
731323334353637383940316396130165201238276315355100,000???2s
84142434445464748495041831261702152613083564054551,000,000???15s
95152535455565758596051103156210265321378436495555
106162636465666768697061123186250315381448516585655=ROWS(B4#)
1171727374757677787980711432162903654415185966757551000000
128182838485868788899081163246330415501588676765855
1391929394959697989910091183276370465561658756855955=ROWS(M4#)
1410110210310410510610710810911010120330641051562172883694510551000000
1511111211311411511611711811912011122333645056568179891610351155
1612112212312412512612712812913012124336649061574186899611251255
Sheet1
Cell Formulas
RangeFormula
B3,X13,X10,M3B3=FORMULATEXT(B4)
B4:K1000003B4=SEQUENCE(1000000,10)
M4:V1000003M4=SCANR(0,B4#,SUM)
X11X11=ROWS(B4#)
X14X14=ROWS(M4#)
Dynamic array formulas.
Lambda Functions
NameFormula
SCANBY=LAMBDA(v₀,▦,λ,[·⇉],[↕],LET(a,IF(↕,TRANSPOSE(▦),▦),c,COLUMNS(a),s,IF(·⇉,SCAN(0,SEQUENCE(ROWS(▦),c),LAMBDA(v,i,LET(m,MOD(i-1,c),q,QUOTIENT(i-1,c)+1,x,INDEX(▦,q,m+1),IF(m,λ(v,x),IF(ISOMITTED(v₀),x,λ(v₀,x)))))),SCAN(v₀,a,λ)),IF(↕,TRANSPOSE(s),s)))
SCANBYROW=LAMBDA(initial_value,array,fn, LET( rows_,ROWS(array), cols_,COLUMNS(array), row_thunks, BYROW(array, LAMBDA(row_, LAMBDA(SCAN(initial_value,row_,fn)) ) ), MAKEARRAY(rows_,cols_, LAMBDA(i,j, INDEX( INDEX(row_thunks,i,1)(), 1, j ) ) ) ) )
SCANC=LAMBDA(v₀,▦,λ,TRANSPOSE(SCANR(v₀,TRANSPOSE(▦),λ)))
SCANR=LAMBDA(v₀,▦,λ,LET(c,COLUMNS(▦),SCAN(0,SEQUENCE(ROWS(▦),c),LAMBDA(v,i,LET(m,MOD(i-1,c),q,QUOTIENT(i-1,c)+1,x,INDEX(▦,q,m+1),IF(m,λ(v,x),IF(ISOMITTED(v₀),x,λ(v₀,x))))))))
TIMEIT=LAMBDA(·🕑,ƒ,IF(ROWS(ƒ),TEXT(MOD(NOW()-TODAY()-·🕑,1),"[hh]:mm:ss.000")))

SCANBY.xlsx
ABCDEFGHIJKLMNOPQRSTUV
1
2SCANSCANRSCANCdblT SCAN
3=SCAN(,B4:D6,CONCAT)=SCANR(,B4:D6,CONCAT)=SCANC(,B4:D6,CONCAT)=TRANSPOSE(SCAN(,TRANSPOSE(B4:D6),CONCAT))
4abcaababcaababcabcaadgbadgbehc
5defabcdabcdeabcdefddedefadbecfadadgbeadgbehcf
6ghiabcdefgabcdefghabcdefghigghghiadgbehcfiadgadgbehadgbehcfi
7
8=SCAN(,B4:D6,LAMBDA(v,i,i&v))=SCANR(,B4:D6,LAMBDA(v,i,i&v))=SCANC(,B4:D6,LAMBDA(v,i,i&v))=TRANSPOSE(SCAN(,TRANSPOSE(B4:D6),LAMBDA(v,i,i&v)))
9abacbaabacbaabcabgdachebgda
10dcbaedcbafedcbadedfeddaebfcdaebgdafchebgda
11gfedcbahgfedcbaihgfedcbaghgihggdahebifcgdahebgdaifchebgda
12
13=SCAN("|",B4:D6,CONCAT)=SCANR("|",B4:D6,CONCAT)=SCANC("|",B4:D6,CONCAT)=TRANSPOSE(SCAN("|",TRANSPOSE(B4:D6),CONCAT))
14|a|ab|abc|a|ab|abc|a|b|c|a|adgb|adgbehc
15|abcd|abcde|abcdef|d|de|def|ad|be|cf|ad|adgbe|adgbehcf
16|abcdefg|abcdefgh|abcdefghi|g|gh|ghi|adg|beh|cfi|adg|adgbeh|adgbehcfi
17
18=SCAN("|",B4:D6,LAMBDA(v,i,i&v))=SCANR("|",B4:D6,LAMBDA(v,i,i&v))=SCANC("|",B4:D6,LAMBDA(v,i,i&v))=TRANSPOSE(SCAN("|",TRANSPOSE(B4:D6),LAMBDA(v,i,i&v)))
19a|ba|cba|a|ba|cba|a|b|c|a|bgda|chebgda|
20dcba|edcba|fedcba|d|ed|fed|da|eb|fc|da|ebgda|fchebgda|
21gfedcba|hgfedcba|ihgfedcba|g|hg|ihg|gda|heb|ifc|gda|hebgda|ifchebgda|
22
23
24=SCAN(,B25#,LAMBDA(v,i,v+2*i))=SCANR(,B25#,LAMBDA(v,i,v+2*i))=SCANC(,B25#,LAMBDA(v,i,v+2*i))=TRANSPOSE(SCAN(,TRANSPOSE(B25#),LAMBDA(v,i,v+2*i)))
252462102221022246254118
2681012385882828521824301874142
2714161811014217814468246566646106178
28
29=SCAN(,B25#,LAMBDA(v,i,v*2+i))=SCANR(,B25#,LAMBDA(v,i,v*2+i))=SCANC(,B25#,LAMBDA(v,i,v*2+i))=TRANSPOSE(SCAN(,TRANSPOSE(B25#),LAMBDA(v,i,v*2+i)))
3028222822246280718
315211424082664121824121701448
32494100420261444106385266383562914
33
34=SCAN(10,B25#,LAMBDA(v,i,v+2*i))=SCANR(10,B25#,LAMBDA(v,i,v+2*i))=SCANC(10,B25#,LAMBDA(v,i,v+2*i))=TRANSPOSE(SCAN(10,TRANSPOSE(B25#),LAMBDA(v,i,v+2*i)))
351422341422341418221466130
365070942646703038463086154
37122154190387010658708258118190
38
39=SCAN(10,B25#,LAMBDA(v,i,v*2+i))=SCANR(10,B25#,LAMBDA(v,i,v*2+i))=SCANC(10,B25#,LAMBDA(v,i,v*2+i))=TRANSPOSE(SCAN(10,TRANSPOSE(B25#),LAMBDA(v,i,v*2+i)))
4022481022248102222426222401998
412124348802866144525864524904008
4217743564714634841861181321461189968034
43
Sheet2
Cell Formulas
RangeFormula
F3,R39,N39,J39,F39,R34,N34,J34,F34,R29,N29,J29,F29,R24,N24,J24,F24,R18,N18,J18,F18,R13,N13,J13,F13,R8,N8,J8,F8,R3,N3,J3F3=FORMULATEXT(F4)
F4:H6F4=SCAN(,B4:D6,CONCAT)
J4:L6J4=SCANR(,B4:D6,CONCAT)
N4:P6N4=SCANC(,B4:D6,CONCAT)
R4:T6R4=TRANSPOSE(SCAN(,TRANSPOSE(B4:D6),CONCAT))
F9:H11F9=SCAN(,B4:D6,LAMBDA(v,i,i&v))
J9:L11J9=SCANR(,B4:D6,LAMBDA(v,i,i&v))
N9:P11N9=SCANC(,B4:D6,LAMBDA(v,i,i&v))
R9:T11R9=TRANSPOSE(SCAN(,TRANSPOSE(B4:D6),LAMBDA(v,i,i&v)))
F14:H16F14=SCAN("|",B4:D6,CONCAT)
J14:L16J14=SCANR("|",B4:D6,CONCAT)
N14:P16N14=SCANC("|",B4:D6,CONCAT)
R14:T16R14=TRANSPOSE(SCAN("|",TRANSPOSE(B4:D6),CONCAT))
F19:H21F19=SCAN("|",B4:D6,LAMBDA(v,i,i&v))
J19:L21J19=SCANR("|",B4:D6,LAMBDA(v,i,i&v))
N19:P21N19=SCANC("|",B4:D6,LAMBDA(v,i,i&v))
R19:T21R19=TRANSPOSE(SCAN("|",TRANSPOSE(B4:D6),LAMBDA(v,i,i&v)))
B25:D27B25=SEQUENCE(3,3,2,2)
F25:H27F25=SCAN(,B25#,LAMBDA(v,i,v+2*i))
J25:L27J25=SCANR(,B25#,LAMBDA(v,i,v+2*i))
N25:P27N25=SCANC(,B25#,LAMBDA(v,i,v+2*i))
R25:T27R25=TRANSPOSE(SCAN(,TRANSPOSE(B25#),LAMBDA(v,i,v+2*i)))
F30:H32F30=SCAN(,B25#,LAMBDA(v,i,v*2+i))
J30:L32J30=SCANR(,B25#,LAMBDA(v,i,v*2+i))
N30:P32N30=SCANC(,B25#,LAMBDA(v,i,v*2+i))
R30:T32R30=TRANSPOSE(SCAN(,TRANSPOSE(B25#),LAMBDA(v,i,v*2+i)))
F35:H37F35=SCAN(10,B25#,LAMBDA(v,i,v+2*i))
J35:L37J35=SCANR(10,B25#,LAMBDA(v,i,v+2*i))
N35:P37N35=SCANC(10,B25#,LAMBDA(v,i,v+2*i))
R35:T37R35=TRANSPOSE(SCAN(10,TRANSPOSE(B25#),LAMBDA(v,i,v+2*i)))
F40:H42F40=SCAN(10,B25#,LAMBDA(v,i,v*2+i))
J40:L42J40=SCANR(10,B25#,LAMBDA(v,i,v*2+i))
N40:P42N40=SCANC(10,B25#,LAMBDA(v,i,v*2+i))
R40:T42R40=TRANSPOSE(SCAN(10,TRANSPOSE(B25#),LAMBDA(v,i,v*2+i)))
Dynamic array formulas.
Lambda Functions
NameFormula
SCANBY=LAMBDA(v₀,▦,λ,[·⇉],[↕],LET(a,IF(↕,TRANSPOSE(▦),▦),c,COLUMNS(a),s,IF(·⇉,SCAN(0,SEQUENCE(ROWS(▦),c),LAMBDA(v,i,LET(m,MOD(i-1,c),q,QUOTIENT(i-1,c)+1,x,INDEX(▦,q,m+1),IF(m,λ(v,x),IF(ISOMITTED(v₀),x,λ(v₀,x)))))),SCAN(v₀,a,λ)),IF(↕,TRANSPOSE(s),s)))
SCANBYROW=LAMBDA(initial_value,array,fn, LET( rows_,ROWS(array), cols_,COLUMNS(array), row_thunks, BYROW(array, LAMBDA(row_, LAMBDA(SCAN(initial_value,row_,fn)) ) ), MAKEARRAY(rows_,cols_, LAMBDA(i,j, INDEX( INDEX(row_thunks,i,1)(), 1, j ) ) ) ) )
SCANC=LAMBDA(v₀,▦,λ,TRANSPOSE(SCANR(v₀,TRANSPOSE(▦),λ)))
SCANR=LAMBDA(v₀,▦,λ,LET(c,COLUMNS(▦),SCAN(0,SEQUENCE(ROWS(▦),c),LAMBDA(v,i,LET(m,MOD(i-1,c),q,QUOTIENT(i-1,c)+1,x,INDEX(▦,q,m+1),IF(m,λ(v,x),IF(ISOMITTED(v₀),x,λ(v₀,x))))))))
TIMEIT=LAMBDA(·🕑,ƒ,IF(ROWS(ƒ),TEXT(MOD(NOW()-TODAY()-·🕑,1),"[hh]:mm:ss.000")))
 
@Xlambda Good stuff! It's nice to see the algorithms for this, to be used with INDEX.

Another approach I've seen is to use the EXPAND function to add a column to the array and use that as the reset point for each row, then DROP the additional column afterwards. This method is easy enough to customize on a case-by-case basis, but as a generalized lambda function it might look something like this:

Excel Formula:
SCANR:
=LAMBDA(init_val,arr,func,LET(rs,CHAR(30),DROP(SCAN(init_val,EXPAND(arr,,COLUMNS(arr)+1,rs),LAMBDA(a,v,IF(v=rs,v,func(IF(a=rs,init_val,a),v)))),,-1)))

SCANC:
=LAMBDA(init_val,arr,func,LET(rs,CHAR(30),DROP(TRANSPOSE(SCAN(init_val,TRANSPOSE(EXPAND(arr,ROWS(arr)+1,,rs)),LAMBDA(a,v,IF(v=rs,v,func(IF(a=rs,init_val,a),v))))),-1)))

Alternatively, recursive lambda functions could be defined using bisection to work around stack limits:

Excel Formula:
SCANBiROW:
=LAMBDA(init_val,arr,func,
    IF(
        ROWS(arr) = 1,
        SCAN(init_val, arr, func),
        VSTACK(
            SCANBiROW(init_val, TAKE(arr, ROWS(arr) / 2), func),
            SCANBiROW(init_val, DROP(arr, ROWS(arr) / 2), func)
        )
    )
)

SCANBiCOL:
=LAMBDA(init_val,arr,func,
    IF(
        COLUMNS(arr) = 1,
        SCAN(init_val, arr, func),
        HSTACK(
            SCANBiCOL(init_val, TAKE(arr,, COLUMNS(arr) / 2), func),
            SCANBiCOL(init_val, DROP(arr,, COLUMNS(arr) / 2), func)
        )
    )
)

Source: Recursive LAMBDA implementation of Excel's REDUCE function
 
Another reason why this place is the best excel laboratory in the world. It's so easy to post examples next to any custom made or copy-pasted formulas from other sources.
Every new array resizing functions are built on top of INDEX.
First test, first function. Function wrong.
I have no time for speed tests.
SCANBY.xlsx
ABCDEFGHIJKLMNOPQRSTUVW
1
2regular SCAN function for each row => no doubts that this is the correct result
3
4781045803080527898188348408568672=SCAN(,B4:H4,LAMBDA(v,i,v+2*i))
58145725896537081171315431623729869=SCAN(,B5:H5,LAMBDA(v,i,v+2*i))
6103090815899141070250412528726754=SCAN(,B6:H6,LAMBDA(v,i,v+2*i))
72694945013726026214402502528672792=SCAN(,B7:H7,LAMBDA(v,i,v+2*i))
86361444697346463185273365559627755=SCAN(,B8:H8,LAMBDA(v,i,v+2*i))
9
10=AND(J4:P8=J11#)=SCANR(,B4:H8,LAMBDA(v,i,v+2*i))
11TRUE7898188348408568672
1281171315431623729869
131070250412528726754
1426214402502528672792
1563185273365559627755
16djclement's function
17J18:=LAMBDA(init_val,arr,func,LET(rs,CHAR(30),DROP(SCAN(init_val,EXPAND(arr,,COLUMNS(arr)+1,rs),LAMBDA(a,v,IF(v=rs,v,func(IF(a=rs,init_val,a),v)))),,-1)))(,B4:H8,LAMBDA(v,i,v+2*i))
187898188348408568672
19=AND(J18#=J4:P8)162252396512704810950
20FALSE=>wrong results2080260422538736764
2152240428528554698818
22126248336428622690818
23
24Recursion solution concept logic flaw: Why to use a solution that has limits that can be overrided or not, if I can use a solution that has no limits, is similar with the native one and is lighting fast.
25Recursion is so nice when we relay on unpredictable exit conditions.
26
Sheet4
Cell Formulas
RangeFormula
J4:P8J4=SCAN(,B4:H4,LAMBDA(v,i,v+2*i))
Q4:Q8Q4=FORMULATEXT(J4)
G10,J10,E19G10=FORMULATEXT(G11)
G11G11=AND(J4:P8=J11#)
J11:P15J11=SCANR(,B4:H8,LAMBDA(v,i,v+2*i))
E17E17=FORMULATEXT(J18)
J18:P22J18=LAMBDA(init_val,arr,func,LET(rs,CHAR(30),DROP(SCAN(init_val,EXPAND(arr,,COLUMNS(arr)+1,rs),LAMBDA(a,v,IF(v=rs,v,func(IF(a=rs,init_val,a),v)))),,-1)))(,B4:H8,LAMBDA(v,i,v+2*i))
E20E20=AND(J18#=J4:P8)
Dynamic array formulas.
Lambda Functions
NameFormula
SCANBY=LAMBDA(v₀,▦,λ,[·⇉],[↕],LET(a,IF(↕,TRANSPOSE(▦),▦),c,COLUMNS(a),s,IF(·⇉,SCAN(0,SEQUENCE(ROWS(▦),c),LAMBDA(v,i,LET(m,MOD(i-1,c),q,QUOTIENT(i-1,c)+1,x,INDEX(▦,q,m+1),IF(m,λ(v,x),IF(ISOMITTED(v₀),x,λ(v₀,x)))))),SCAN(v₀,a,λ)),IF(↕,TRANSPOSE(s),s)))
SCANBYROW=LAMBDA(initial_value,array,fn, LET( rows_,ROWS(array), cols_,COLUMNS(array), row_thunks, BYROW(array, LAMBDA(row_, LAMBDA(SCAN(initial_value,row_,fn)) ) ), MAKEARRAY(rows_,cols_, LAMBDA(i,j, INDEX( INDEX(row_thunks,i,1)(), 1, j ) ) ) ) )
SCANC=LAMBDA(v₀,▦,λ,TRANSPOSE(SCANR(v₀,TRANSPOSE(▦),λ)))
SCANR=LAMBDA(v₀,▦,λ,LET(c,COLUMNS(▦),SCAN(0,SEQUENCE(ROWS(▦),c),LAMBDA(v,i,LET(m,MOD(i-1,c),q,QUOTIENT(i-1,c)+1,x,INDEX(▦,q,m+1),IF(m,λ(v,x),IF(ISOMITTED(v₀),x,λ(v₀,x))))))))
TIMEIT=LAMBDA(·🕑,ƒ,IF(ROWS(ƒ),TEXT(MOD(NOW()-TODAY()-·🕑,1),"[hh]:mm:ss.000")))
 

Forum statistics

Threads
1,224,813
Messages
6,181,117
Members
453,021
Latest member
Justyna P

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top