0

I am trying to familiarize with itertools. As an exercise, I am trying to generate (x,y) integer pairs satisfying -1 < y < x <5. The following code using itertools produces incorrect results:

from itertools import *
xs = xrange(0,5)
allPairs = chain(*(izip(repeat(x), takewhile(lambda y: y < x, count())) for x in xs))
print list(allPairs)

The output is

[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (3, 0), (3, 1), (3, 2), (3, 3), (4, 0), (4, 1), (4, 2), (4, 3)]

The problem seems to be that the lambda function within the takewhile is using x = 4, the maximum in the range.

If I modify the code above to explicitly construct a lambda function for each x as follows the output is computed correctly.

from itertools import *
xs = xrange(0,5)
xypair = lambda x: izip(repeat(x), takewhile(lambda y: y < x, count()))

allPairs = chain(*(xypair(x) for x in xs))
print list(allPairs)

Output:

[(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3)]

Any idea why in the first code the lambda is constructed only using the last value of the iteration over xs?

1 Answers1

0

Try something a bit simpler:

combinations(iterable,r): r-length tuples, in sorted order, no repeated elements

>>> list(combinations(xrange(0,5),2))
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
jtbandes
  • 115,675
  • 35
  • 233
  • 266