To get a true cross join or Cartesian product, use a recursive lambda function, like this:
=let(
values, torow(A2:A, 1),
zeros, map(values, lambda(_, 0)),
table, { zeros; values },
first_, lambda(array, tocol(choosecols(array, 1), true)),
rest_, lambda(n, choosecols(table, sequence(1, columns(table) - n, n + 1))),
wrap_, lambda(array, wrapCount, wraprows(tocol(array, 1), wrapCount)),
cartesian_, lambda(a, b, wrap_(
byrow(a, lambda(row,
reduce(iferror(ø), sequence(rows(b)), lambda(acc, i,
{ acc, row, chooserows(b, i) }
) )
) ),
columns(a) + columns(b)
) ),
iterate_, lambda(
self, a, b, if(iserror(b), a,
self(self, cartesian_(a, first_(b)), rest_(columns(a) + 1))
)
),
cartesian, iterate_(iterate_, first_(table), rest_(1)),
sums, byrow(cartesian, lambda(row, sum(row))),
expressions, byrow(cartesian, lambda(row, join(" + ", filter(row, row)))),
result, unique(filter({ expressions, sums }, sums)),
key, choosecols(result, 1),
sort(result, left(key), true, len(key), true, key, true)
)
The results will look like this:
data set |
combinations |
total |
1 |
1 |
1 |
2 |
1 + 2 |
3 |
3 |
1 + 3 |
4 |
4 |
1 + 4 |
5 |
|
1 + 2 + 3 |
6 |
|
1 + 2 + 4 |
7 |
|
1 + 3 + 4 |
8 |
|
1 + 2 + 3 + 4 |
10 |
|
2 |
2 |
|
2 + 3 |
5 |
|
2 + 4 |
6 |
|
2 + 3 + 4 |
9 |
|
3 |
3 |
|
3 + 4 |
7 |
|
4 |
4 |
To do the same with any values, such as text strings or dates, use this pattern:
=let(
values, torow(filter(to_text(A2:A), len(A2:A))),
blanks, map(values, lambda(_, "")),
table, { blanks; values },
first_, lambda(array, tocol(choosecols(array, 1), true)),
rest_, lambda(n, choosecols(table, sequence(1, columns(table) - n, n + 1))),
wrap_, lambda(array, wrapCount, wraprows(tocol(array, 1), wrapCount)),
cartesian_, lambda(a, b, wrap_(
byrow(a, lambda(row,
reduce(iferror(ø), sequence(rows(b)), lambda(acc, i,
{ acc, row, chooserows(b, i) }
) )
) ),
columns(a) + columns(b)
) ),
iterate_, lambda(
self, a, b, if(iserror(b), a,
self(self, cartesian_(a, first_(b)), rest_(columns(a) + 1))
)
),
cartesian, iterate_(iterate_, first_(table), rest_(1)),
expressions, byrow(cartesian, lambda(r, join(" + ", filter(r, len(r))))),
result, tocol(expressions, 3),
sort(result, left(result), true, len(result), true, result, true)
)
The results will look like this:
data set |
combinations |
a |
a |
b |
a + b |
c |
a + c |
d |
a + d |
|
a + b + c |
|
a + b + d |
|
a + c + d |
|
a + b + c + d |
|
b |
|
b + c |
|
b + d |
|
b + c + d |
|
c |
|
c + d |
|
d |