# Cleanest way to generate all combinations of n arrays

**URL:** https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127
**Category:** General Usage
**Created:** [January 26, 2019, 1:26pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127 "2019-01-26T13:26:09Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![srb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/srb/32/6812_2.png) [@srb](https://discourse.julialang.org/u/srb)
#### Post date: [January 26, 2019, 1:26pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/1 "2019-01-26T13:26:09Z")

</div>

What I am trying to get is all the possible values given an array `[0, 1, 2]` and a number `n`. The result for `n=3` would be:

```julia
[0,0,0]
[0,0,1],
[0,0,2]
[0,1,0]
...
[2,2,2]

```

So basically all the numbers in base 3 given as separate elements in an array.

I have been trying to get this output by using `Base.Iterators.product([0,1,2],[0,1,2],[0,1,2])`and this does indeed work but I’m having trouble finding a way to be able to do so programatically, as I can’t pass the arguments to `product` separately.

I tried generating the list of arrays by using `repeat([0,1,2], 1, n)` and this does give me a matrix of n columns with each being one `[0, 1, 2]` arrays, but I can’t find a way to pass each of these columns separately as input to `product()`

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [January 26, 2019, 2:21pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/2 "2019-01-26T14:21:03Z")

</div>

[splatting](https://docs.julialang.org/en/v1/base/base/#...)?

---

<div class="post-metadata">

### Author: ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)
#### Post date: [January 26, 2019, 2:32pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/3 "2019-01-26T14:32:10Z")

</div>

Let me get you an answer.

---

<div class="post-metadata">

### Author: ![srb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/srb/32/6812_2.png) [@srb](https://discourse.julialang.org/u/srb)
#### Post date: [January 26, 2019, 2:41pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/4 "2019-01-26T14:41:50Z")

</div>

I tried this but splatting a 3x3 array does not give you 3 1x3 arrays (and `product` expects n iterables as argument.

```julia
julia> x = repeat([1,2,3],1,3)
3×3 Array{Int64,2}:
 1 1 1
 2 2 2
 3 3 3

julia> collect(Base.Iterators.product(x...))
0-dimensional Array{NTuple{9,Int64},0}:
(1, 2, 3, 1, 2, 3, 1, 2, 3)

julia>

```

---

<div class="post-metadata">

### Author: ![RoyiAvital](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/royiavital/32/571_2.png) [@RoyiAvital](https://discourse.julialang.org/u/RoyiAvital)
#### Post date: [January 26, 2019, 3:00pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/5 "2019-01-26T15:00:33Z")

</div>

Probably not efficient but one way to do so is built the representation of this ternary number.

So you should do a loop up to `3 ^ n - 1` and for each number build its representation per index.

---

<div class="post-metadata">

### Author: ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)
#### Post date: [January 26, 2019, 3:30pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/6 "2019-01-26T15:30:21Z")

</div>

```julia
N = 3
lpad.(string.(0:N^N-1;base=N),N,'0').|>s->Int.(collect(s).-48)

```

Not the most efficient 🙂

---

<div class="post-metadata">

### Author: ![fnin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fnin/32/23300_2.png) [@fnin](https://discourse.julialang.org/u/fnin)
#### Post date: [January 26, 2019, 3:37pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/7 "2019-01-26T15:37:24Z")

</div>

This is a naive Combinations iterator, doing something similar to what bennedich proposed.

```julia
import Base.iterate,Base.length
struct Combinations{T}
    itr::Vector{T}
    count::Int64
    itrsize::Int64
    function Combinations(itr::Vector{T},count::Int) where T
        new{T}(itr,Int64(count),length(itr))
    end
end

function iterate(c::Combinations,state::Int64=0)
    if state>=length(c)
        return nothing
    end
    indices=digits(state,base=c.itrsize,pad=c.count)
    [c.itr[i] for i in (indices .+1)],state+1
end

function length(c::Combinations)
    length(c.itr) ^ c.count
end

julia> collect(Combinations([0,1,2],3))
27-element Array{Any,1}:
 [0, 0, 0]
 [1, 0, 0]
 [2, 0, 0]
 [0, 1, 0]
 [1, 1, 0]
 [2, 1, 0]
 [0, 2, 0]
 [1, 2, 0]
 [2, 2, 0]
 [0, 0, 1]
 [1, 0, 1]
 [2, 0, 1]
 [0, 1, 1]
 [1, 1, 1]
 [2, 1, 1]
 [0, 2, 1]
 [1, 2, 1]
 [2, 2, 1]
 [0, 0, 2]
 [1, 0, 2]
 [2, 0, 2]
 [0, 1, 2]
 [1, 1, 2]
 [2, 1, 2]
 [0, 2, 2]
 [1, 2, 2]
 [2, 2, 2]

```

---

<div class="post-metadata">

### Author: ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)
#### Post date: [January 26, 2019, 3:42pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/8 "2019-01-26T15:42:21Z")

</div>

Here’s how to do it with `Iterators.product`:

```julia
N = 3
reverse.(Iterators.product(fill(0:N-1,N)...))[:]

```

---

<div class="post-metadata">

### Author: ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)
#### Post date: [January 26, 2019, 4:11pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/9 "2019-01-26T16:11:41Z")

</div>

Recursive lambda comprehension:

```julia
N = 3
(p=(a,c)->c<2 ? a : [[x;y] for x=a for y=p(a,c-1)])(0:N-1,N)

```

---

<div class="post-metadata">

### Author: ![improbable22](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/improbable22/32/5464_2.png) [@improbable22](https://discourse.julialang.org/u/improbable22)
#### Post date: [January 26, 2019, 4:58pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/10 "2019-01-26T16:58:21Z")

</div>

Here’s a way using `digits`:

```julia
fun(arr::Vector, num::Int) = 
    [getindex.(Ref(arr), 1 .+ digits(i-1; base=length(arr), pad=num)) for i=1:length(arr)^num]

fun(["oh","1","2"],3)

```

---

<div class="post-metadata">

### Author: ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)
#### Post date: [January 26, 2019, 6:17pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/11 "2019-01-26T18:17:55Z")

</div>

Briefer:

```julia
N = 3
reverse.(digits.(0:N^N-1,base=N,pad=N))

```

---

<div class="post-metadata">

### Author: ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)
#### Post date: [January 26, 2019, 8:09pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/12 "2019-01-26T20:09:49Z")

</div>

You can also try:

```julia
Iterators.product(ntuple(i->0:N-1, N)...)

```

---

<div class="post-metadata">

### Author: ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)
#### Post date: [April 3, 2019, 2:27pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/14 "2019-04-03T14:27:31Z")

</div>

See: [Julia docs FAQ - The two uses of the `...` operator - slurping and splatting](https://docs.julialang.org/en/v1/manual/faq/index.html#The-two-uses-of-the-...-operator:-slurping-and-splatting-1)

---

<div class="post-metadata">

### Author: ![Johncowk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johncowk/32/8032_2.png) [@Johncowk](https://discourse.julialang.org/u/Johncowk)
#### Post date: [April 9, 2019, 12:49pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/16 "2019-04-09T12:49:17Z")

</div>

Does anybody know an optimized solution for this problem ?  
I need to write a code that generates all of the possible patterns in a set of categorical data and it turns out that generating the combination is really the step that makes the overall operation incredibly slow (takes about 25 minutes tand then ends up into a memory error when I do it with real data).  
I have tried using for loops :

```julia
function withloops(x,y)
    leny=length(y)
    lenx=length(x)
    m=leny*lenx
    OUT = zeros(Float64, m,2)
    c=1
    for i = 1:lenx
        for j = 1:leny
            OUT[c,1] = x[i]
            OUT[c,2] = y[j]
            c+=1
        end
    end
    return OUT
end

```

I also tried what @bennedich and @improbable22 suggested :

```julia
reverse.(Iterators.product(fill(0:N-1,N)...))[:] 

```

and

```julia
[getindex.(Ref(arr), 1 .+ digits(i-1; base=length(arr), pad=num)) for i=1:length(arr)^num]

```

turns out solution using Iterators.product is the most efficient but it still is too much for my computer.  
Is there a better way to do it ?

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [April 9, 2019, 1:25pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/17 "2019-04-09T13:25:15Z")

</div>

You realize this is an exponential operation in terms of both time and memory, right? It is O(K^N) where K is the base and N is the length of the number. Moreover, by asking to materialize all of these digit combinations all at once, it forces the problem to not only have exponential run time but also to allocate exponential memory. This brute force approach is only going to work for tiny toy problems.

You’d be much better off not materializing all the arrays at once. Even better still would be not materializing then at all and allowing them to be represented implicitly as integers: you can then iterate through them very quickly and ask properties of them as integers. If you want something really fast and scalable you need to avoid considering most of the combinations at all.

Hard to give more advice without knowing what you’re trying to compute.

---

<div class="post-metadata">

### Author: ![Johncowk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johncowk/32/8032_2.png) [@Johncowk](https://discourse.julialang.org/u/Johncowk)
#### Post date: [April 9, 2019, 2:16pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/18 "2019-04-09T14:16:00Z")

</div>

@StefanKarpinski Yes you are right … but I have no idea how to do this with integers.  
What I am trying to do is the following : given N categories, find out all the possible combinations of n (among N) elements, with allowed repetition. Then look at the frequency of occurence of each of these patterns in the data to try to identify patterns.  
Since I also want to look at the possibility to vary the space ordering of the elements inside of a pattern, it does indeed generate a huge amount of combinations.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [April 11, 2019, 2:18pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/19 "2019-04-11T14:18:45Z")

</div>

If it’s based on data then you know that all K^N combinations cannot possibly happen for large values of K and N. So instead of scanning for all the possibilities—which would be O(D\*K^N) where D is the size of the data—just scan the data once and record all the combinations that actually occur which will only be O(D). It’s a linear scan of your data; hard to do better than that.

---

<div class="post-metadata">

### Author: ![ga72kud](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ga72kud/32/32180_2.png) [@ga72kud](https://discourse.julialang.org/u/ga72kud)
#### Post date: [January 10, 2022, 1:49pm UTC](https://discourse.julialang.org/t/cleanest-way-to-generate-all-combinations-of-n-arrays/20127/20 "2022-01-10T13:49:38Z")

</div>

for my problem this helped me  
`collect(Iterators.product(-1:1, -1:1))[:]`
