Python for loop offset(Itertools.product)

时间:2014-02-12 17:13:52

标签: python performance for-loop offset itertools

以下代码使用01生成所有可能的组合,其中必须使用四位数。

import itertools
for i in itertools.product([0, 1], repeat=4):
    print i

输出:

(0, 0, 0, 0)(0, 0, 0, 1)(0, 0, 1, 0)(0, 0, 1, 1)(0, 1, 0, 0)(0, 1, 0, 1)(0, 1, 1, 0)(0, 1, 1, 1)(1, 0, 0, 0)(1, 0, 0, 1)(1, 0, 1, 0)(1, 0, 1, 1)(1,1, 0, 0)(1, 1, 0, 1)(1, 1, 1, 0)(1, 1, 1, 1)

我希望能够为for循环设置偏移量。例如:

import itertools
offSet = 10
for i in itertools.product([0, 1], repeat=4):
    # Some code that applies the offset
    print i

然后输出:

(1, 0, 1, 0)(1, 0, 1, 1)(1,1, 0, 0)(1, 1, 0, 1)(1, 1, 1, 0)(1, 1, 1, 1)

如何将此类偏移应用于此for循环?

注意:正在使用的代码已经过简化。由于我实际使用repeat的非常大的值,性能很重要。在计算偏移量之前,我买不起可能的组合。

3 个答案:

答案 0 :(得分:1)

这个怎么样:

In [29]: offSet = 10

In [30]: repeat = 4

In [31]: for i in xrange(offSet, 2**repeat):
    print tuple(int(x) for x in bin(i)[2:])
   ....:     
(1, 0, 1, 0)
(1, 0, 1, 1)
(1, 1, 0, 0)
(1, 1, 0, 1)
(1, 1, 1, 0)
(1, 1, 1, 1)

答案 1 :(得分:1)

这是一个定义,它采用二进制文件(在Python中,由'0b1010101'中的字符串表示)(或简单的人类可读写版本,省略0b部分)并返回范围以字符串元组的迭代器的形式(它是懒惰地创建)。您可以使用list()来实现范围。

def binrange(start, stop=None):
    '''
    given bin strings return iterator of zeros and ones
    e.g. 
    >>> list(binrange(bin(8))) # bin(8) returns '0b1000'
    [(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1)]
    >>> list(binrange('10', bin(4))) # bin(4) returns '0b100'
    [(0, 1, 0), (0, 1, 1)]
    '''
    if stop is None:
        start, stop = '0', start
    start = start[2:] if start.startswith('0b') else start
    stop = stop[2:] if stop.startswith('0b') else stop
    length = len(stop)
    for i in xrange(long(start, 2), long(stop, 2)): # in Python3, use range(), not xrange()
        yield tuple(int(j) for j in ('{0:b}'.format(i).zfill(length)))
        # above line replaces the following commented line
        # yield tuple(int(j) for j in ('{0:{fill}{align}{width}b}'.format(i, fill=0, align='>', width=length)))

print(list(binrange(bin(1000**3), bin(1000**3+3))))
print(list(binrange('1000')))
print(list(binrange('0b100')))

打印出来:

[(1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), (1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1), (1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0)]
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1)]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)]

答案 2 :(得分:0)

您可以使用islice

from itertools import product, islice

i = islice(product([0, 1], repeat=4), 10, None) 
print list(i)

对于:

,这仍然失败
  

在计算偏移量之前,我买不起可能的组合。

这不是迭代器的用途。无论如何,你实际上只是想用二进制来计算,其他答案在这里可行