2

I have a list and would like to generate a finite number of permutation with no repeated elements.

itertools.permutations(x)

gives all possible orderings but I only need a specific number of permutation. (my initial list contains ~200 elements => 200! will take an unreasonable amount of time and I don't need all of them)

what I have done so far

def createList(My_List):
    New_List = random.sample(My_List, len(My_List))
    return New_List

def createManyList(Nb_of_Lists):
    list_of_list = []
    for i in range(0, Nb_of_Lists):
        list_of_list.append(createList())
    return list_of_list

It's working but my List_of_list will not have unique permutations or at least I have no guaranty about it.

Is there any way around to do so? Thanks

2

3 Answers 3

5

Just use islice, which allows you to take a number of elements from an iterable:

from itertools import permutations, islice

n_elements = 1000

list(islice(permutations(x), 0, 1000))

This will return a list of (the first) 1000 permutations.

The reason this works is that permutations returns an iterator, which is an object that generates values to return as they are needed, not immediately. Therefore, the process goes something like this:

  1. The calling function (in this case, list) asks for the next value from islice
  2. islice checks if 1000 values have been returned; if not, it asks for the next value from permutations
  3. permutations returns the next value, in order

Because of this, the full list of permutations never needs to be generated; we take only as many as we want.

Sign up to request clarification or add additional context in comments.

2 Comments

This is the best solution. You might want to add a brief explanation why generators are efficient in python and that all permutations are not actually created and then filtered down to 1000.
Yeah this is the way to go!
1

You can do:

i = 0
while i < Nb_of_Lists:
    if createlist() not in list_of_lists:
        list_of_list.append(createList())
    else:
        i -= 1

This will check if that permutation was already used.

Comments

1

You don't need to roll your own permutation. You just to halt the generator once you get enough:

# python 2.7
import random
import itertools
def createList(My_List):
    New_List = random.sample(My_List, len(My_List))
    return New_List

x = createList(xrange(20))
def getFirst200():
    for i, result in enumerate(itertools.permutations(x)):
        if i == 200:
            raise StopIteration
        yield result

print list(getFirst200()) # print first 200 of the result

This is faster and more memory efficient than 'generate of full set then take first 200' approach

2 Comments

The islice() approach suggested by @gmds is much more cleaner.
Note that in Python 3.6, raise StopIteration in a generator will raise a DeprecationWarning; in Python 3.7, it will raise a RuntimeError.

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.