2014-02-12 59 views
0

以下代码使用01生成所有可能的组合,其中必须使用四位数字。Python for loop offset(Itertools.product)

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,性能问题。在计算偏移量之前,我无法承受可能的组合。

+0

反正是有,你可以“计算”的出发点(这将是特定于您的具体使用情况) - 否则,唯一的办法就是生成价值观并放弃,直到你对它们感兴趣...... –

+1

它只是笛卡儿的产品;如果您不需要生成其中一部分,请将您的问题分解为子集;你在这里有子部分可以用链式产品来生成。 –

+4

它看起来像你试图在整数的两个二进制表示之间。也许只是循环一个'xrange(start,end)'并将整数转换为你需要的二进制格式? – roippi

回答

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

'map(int,“{:b}”.format(a))'也可以在这里使用 – Eric

0

你可以使用islice

from itertools import product, islice 

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

这仍然无法在以下方面:

我无法承受可能的组合前偏移进行计算。

这实际上并不是迭代器的用途。无论如何,你实际上只是试图用二进制数来计算,而其他答案在这里会起作用

+0

islice仍然计算值到起始值,它只是不会返回它们。 – M4rtini

0

下面是一个采用二进制的定义(在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)]