gdogg371 gdogg371 - 1 month ago 20
Python Question

Random and Itertools

I have some sample code that iterates through two different ranges of numbers successfully, but I want to add functionality to it so that it moves through the chained ranges randomly like so:

import itertools
import random

for f in random.sample(itertools.chain(range(30, 54), range(1, 24)), 48):

print f


However this produces the following error:

Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
for f in random.sample(itertools.chain(range(30, 54), range(1, 24)), 48):
File "G:\Python27\lib\random.py", line 321, in sample
n = len(population)
TypeError: object of type 'itertools.chain' has no len()


Can anyone advise the amendments needed to make this function as intended?

Answer

A quick fix would be as follows:

for f in random.sample(list(itertools.chain(range(30, 54), range(1, 24))), 48):

The problem with your code is that to sample from some iterable randomly, you need to know its length first, but itertools.chain is an iterable that provides only the __iter__ method and no __len__.

Basically, to do random.choice or random.sample or anything that involves choosing elements at random, you'll need a sequence or a set, which means that sequence should be finite. Iterables that don't provide the __len__ method are considered infinite as you'll never know how many elements will be produced until the iterable's exhausted, if at all.

Comments