29

I have a numpy array [0, 1, 1, 2, 2, 0, 1, ...] which only contains the numbers 0-k. I would like to create a new array that contains the n possible arrays of permutations of 0-k. A small example with k=2 and n=6:

a = [0, 1, 0, 2]
permute(a)
result = [[0, 1, 0, 2]
          [0, 2, 0, 1]
          [1, 0, 1, 2]
          [2, 1, 2, 0]
          [1, 2, 1, 0]
          [2, 0, 2, 1]]

Does anyone have any ideas/solutions as to how one could achieve this?

2
  • 3
    This is a duplicate plus a google away. Commented Dec 18, 2016 at 15:58
  • 14
    @kabanus OP seems to want distinguishable permutations -- which that link doesn't give. Commented Dec 18, 2016 at 16:02

3 Answers 3

56

Your a is what combinatorists call a multiset. The sympy library has various routines for working with them.

>>> from sympy.utilities.iterables import multiset_permutations
>>> import numpy as np
>>> a = np.array([0, 1, 0, 2])
>>> for p in multiset_permutations(a):
...     p
...     
[0, 0, 1, 2]
[0, 0, 2, 1]
[0, 1, 0, 2]
[0, 1, 2, 0]
[0, 2, 0, 1]
[0, 2, 1, 0]
[1, 0, 0, 2]
[1, 0, 2, 0]
[1, 2, 0, 0]
[2, 0, 0, 1]
[2, 0, 1, 0]
[2, 1, 0, 0]
Sign up to request clarification or add additional context in comments.

3 Comments

did not know about this one. learned something new! thanks! +1
Which is a big reason for my presence here too!
This question didn't ask for multiset permutations though, see the example in the question.
39

if your permutations fit in the memory, you could store them in a set and thus only get the distinguishable permutations.

from itertools import permutations

a = [0, 1, 0, 2]

perms = set(permutations(a))

4 Comments

This is probably okay for small examples, but this involves generating n! permutations when the number of distinguishable permutations might be much smaller
@JohnColeman: i agree. but as i have no idea how big the sample is... it might just work.
As is often the case in Python, it is a question of scale. This is a perfectly good approach for smaller examples (which is why I upvoted it). For larger examples you would want to use a library with multiset support (as the other answer has).
By the way -- set(permutations(a)) is a 1-line implementation of your idea.
0

The other answers don't answer the question, their output doesn't match the example. The question asked to apply all permutations of the values 0,1,2 in the array.

Here is one way to do this:

import numpy as np
from itertools import permutations

a = [0, 1, 0, 2]
ps = np.array(list(permutations([0,1,2])))
result = ps[:,a]

Result, matching the example in the question:

[[0 1 0 2]
 [0 2 0 1]
 [1 0 1 2]
 [1 2 1 0]
 [2 0 2 1]
 [2 1 2 0]]

Explanation: The array ps is

[[0 1 2]
 [0 2 1]
 [1 0 2]
 [1 2 0]
 [2 0 1]
 [2 1 0]]

And the line ps[:,[0,1,0,2]] will select the items 0, 1, 0, 2 for each row. See Integer array indexing

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.