### Question :

I can make a list of all combinations using `list(itertools.combinations(range(n), m))`

but this will typically be very large.

Given

`n`

and`m`

, how can I choose a combination uniformly at random without first constructing a massive list??

##
Answer #1:

From http://docs.python.org/2/library/itertools.html#recipes

```
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(xrange(n), r))
return tuple(pool[i] for i in indices)
```

##
Answer #2:

In the `itertools`

module there is a recipe for returning a random combination from an iterable. Below are two versions of the code, one for Python 2.x and one for Python 3.x – in both cases you are using a generator which means that you are not creating a large iterable in memory.

### Assumes Python 2.x

```
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(xrange(n), r))
return tuple(pool[i] for i in indices)
```

In your case then it would be simple to do:

```
>>> import random
>>> def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(xrange(n), r))
return tuple(pool[i] for i in indices)
>>> n = 10
>>> m = 3
>>> print(random_combination(range(n), m))
(3, 5, 9) # Returns a random tuple with length 3 from the iterable range(10)
```

### In the case of Python 3.x

In the case of Python 3.x you replace the `xrange`

call with `range`

but the use-case is still the same.

```
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(range(n), r))
return tuple(pool[i] for i in indices)
```

##
Answer #3:

A generator would be more memory efficient for iteration:

```
def random_combination(iterable,r):
i = 0
pool = tuple(iterable)
n = len(pool)
rng = range(n)
while i < r:
i += 1
yield [pool[j] for j in random.sample(rng, r)]
```