1

source cell is this string: A[B,C,D]E need to generete all combination into different cells:

ABE
ACE
ADE

Should work with more complicated source like: A[B,C,D]E[F,G]:

ABEF
ACEG
ADEF
ABEG
ACEF
ADEG
JvdV
  • 70,606
  • 8
  • 39
  • 70
Tyvain
  • 2,640
  • 6
  • 36
  • 70

2 Answers2

4

In the event you have access to REDUCE(), you could try:

enter image description here

Formula in B1:

=LET(X,"<t><s>",Y,"</s><s>",Z,"</s></t>",TRANSPOSE(FILTERXML(X&SUBSTITUTE(REDUCE("",FILTERXML(X&SUBSTITUTE(SUBSTITUTE(A1,"]","["),"[",Y)&Z,"//s[node()]"),LAMBDA(a,b,TEXTJOIN(",",,IFERROR(FILTERXML(X&SUBSTITUTE(a,",",Y)&Z,"//s"),"")&TRANSPOSE(FILTERXML(X&SUBSTITUTE(b,",",Y)&Z,"//s"))))),",",Y)&Z,"//s")))

And yes, that's seriously hard to explain in a nutshell, but I'll try it anyway =)

  • The 1st parameter of REDUCE() is our starting value, in our case we want string-values so we use an empty string "". Later on in this function we can refer to this starting value as 'a'.
  • The 2nd parameter is either a range-reference or an array. In this particular case an array since we used FILTERXML() to chop-up the input into different sections.
  • In the 3rd parameter sits a nested LAMBDA(). This function has two custom named variables, 'a' and 'b'. Note that we allready have the 'a' value down in the 1st parameter of REDUCE(). The 'b' value is the value of each of the elements of our array in the 2nd parameter.

The idea here now is that with each pass of the next element the LAMBDA() perform a recursive function. When our first element passes, the essence of the nested function is to concatenate each child-node of the previous element (or empty string in the 1st passing) with each child-node of the current element. REDUCE() will only return the final outcome when all the elements have been passed through LAMBDA().

This final string will then be finally 'split' on itself through FILTERXML(). For a better understanding on this particular function I'd like to refer to this older post.

In the image below I tried to address and visualize this whole process where the input is 'split' into an array which on itself is input for the process to reduce the array. The final outcome is then also 'split'.


enter image description here

JvdV
  • 70,606
  • 8
  • 39
  • 70
3

Edit: My bad, I forgot to combine the characters in different ways. I'll update a fix soon.


Original Answer:

Assuming you are only looking at single character strings to combine, you can do this without a lambda function. Please note, I did not optimize this at all:

=LET(
    Txt, A1,
    Seq, SEQUENCE(LEN(Txt)),
    TxtArr, MID(Txt, Seq, 1),
    Open, IFERROR(FIND("[",TxtArr),0),
    Close, IFERROR(FIND("]",TxtArr),0) * -1,
    Starts, FILTER(Open * Seq, Open <> 0),
    Lens, FILTER(-Close * Seq, Close <> 0) - Starts + 1,
    ORs, SUBSTITUTE(MID(Txt, Starts + 1, Lens - 2),",",""),
    OrGroup, MMULT(IF(Seq >= TRANSPOSE(Seq)=TRUE,1,0),Open),
    Mask, -MMULT(IF(Seq >= TRANSPOSE(Seq)=TRUE,1,0),Open+Close) + 1,
    Masked, MID(Txt, Mask*Seq, 1),
    ReplacedMasked, IF(Masked = "]", INDEX(ORs, OrGroup), Masked),
    CleanArray, FILTER(ReplacedMasked,ISERROR(ReplacedMasked)=FALSE),
    ArrayLens, LEN(CleanArray),
    ArrayProd, PRODUCT(ArrayLens),
    ExtendArray, REPT(CleanArray, ArrayProd/ArrayLens),
    CharacterArray, MID(TRANSPOSE(ExtendArray), SEQUENCE(ArrayProd),1),
    ReturnLen, ROWS(CleanArray),
    MID(CONCAT(CharacterArray), SEQUENCE(ROWS(CharacterArray))* ReturnLen - ReturnLen + 1, ReturnLen)
)

This formula takes your text, and finds brackets. It creates an array of character options called CleanArray. It finds the total number of combinations repeats the characters in CleanArray so that each row contains a string the length of all options. It combines the first character of each string, then the second character of each string, and so on. Last, it concatenates everything together and re-separates it into rows.

A A[B,C] A[B,C][D,E]
A AB ABD
AC ACE
ABD
ACE
Dave Thunes
  • 260
  • 2
  • 9
  • No doubt this took you a long time to produce but job wel done sir! But yes, there is a flaw as you have noticed. Nonetheless + =) – JvdV Oct 26 '21 at 20:03
  • @JcdV, This is taking too long to fix. I have everything working but one part - I need a way to multiply across an array. Is that possible? {1,2;3,4} would become {2;12}. Or, what I really need is a way to get a running product. {1,2,3,4} would become {1,2,6,24}. – Dave Thunes Oct 27 '21 at 16:05
  • Well, `=SCAN(1,{1,2,3,4},LAMBDA(a,b,a*b))` would do exactly that. However, you may not have the function yet if you not a MS365-insider. Any other way without revering to actual ranges will be (near) impossible I guess. See [this](https://stackoverflow.com/q/68400019/9758194) recent post on the topic by @markfitzpatrick – JvdV Oct 27 '21 at 17:13