Intro
DROP/REDUCE/VSTACK combo. Later, when testing my formula with 10k integers (stacks), as you can probably guess, it became unbearable to wait for the result. Is there a way to generate the result more efficiently?The Task
A2:A4. For each next integer, I want to generate a sequence of the size of the integer and stack it below the previously generated one.| Size | Result | |
|---|---|---|
| 2 | 1 | |
| 5 | 2 | |
| 3 | 1 | |
| 2 | ||
| 3 | ||
| 4 | ||
| 5 | ||
| 1 | ||
| 2 | ||
| 3 |
I'm currently using the following (slow) formula:
=LET(data,A2:A4,DROP(REDUCE("",SEQUENCE(ROWS(data)),LAMBDA(rr,r,
VSTACK(rr,SEQUENCE(INDEX(data,r))))),1))
You could generate the large dataset with the formula =RANDARRAY(10000,,1,9,1), then copy/paste values and replace A2:A4 with A2:A10001 in your formula.
I'm primarily interested in a formula for Excel 365 but solutions for Legacy Excel, Power Query, or VBA might be useful to the community.
So, here is one way using Excel Formula:
=LET(_a, A2#, _b, SEQUENCE(, MAX(_a)), TOCOL(IF(_b <= _a, _b, 0/0), 2))
LET() function helps to define variables with the formula, so it can read clearly_a is assigned to the array A2#_b is the sequence of numbers to its the max value of _aIF() logic to determine and compares each element in the sequence with each value in _a, so, when _b less than equal to _a it returns the variable _b else it returns a #DIV/0! errorTOCOL() function, the parameter 2 or 3 can be used which ignores the error or if any empty. Thus giving the requisite output.Also, in place of IF() --> IFS() can be used:
=LET(_a, A2#, _b, SEQUENCE(, MAX(_a)), TOCOL(IFS(_b <= _a, _b), 2))
Since we are dealing with numbers, we use in the following manner as well:
=LET(_a, A2#, _b, SEQUENCE(, MAX(_a)), TOCOL(_b/(_b <= _a), 2))