Abh*_*jit 12 python foreach python-itertools python-2.7
Python的succint语法通过其电池允许详细的代码行以可读的一行表示.请考虑以下示例
====================================================|
for a in range(3): |
for b in range(3): |
for c in range(3): |
print (a,b,c), |
- - - - - - - - - - - - - - - - - -|
for e in product(range(3), repeat=3): |
print e, |
====================================================|
for a in range(3): |
for b in range(a , 3): |
for c in range(b , 3): |
print (a,b,c), |
- - - - - - - - - - - - - - - - - -|
for e in combinations_with_replacement(range(3), 3):|
print e, |
====================================================|
for a in range(3): |
for b in range(a + 1, 3): |
for c in range(b + 1, 3): |
print (a,b,c), |
- - - - - - - - - - - - - - - - - -|
for e in combinations(range(3), 3): |
print e, |
====================================================|
for a in range(3): |
for b in range(3): |
for c in range(3): |
if len(set([a,b,c])) == 3: |
print (a,b,c), |
- - - - - - - - - - - - - - - - - -|
for e in permutations(range(3)): |
print e, |
====================================================|
Run Code Online (Sandbox Code Playgroud)
我最后得到一个深嵌套的依赖循环我试图简洁地表达但失败了
循环的结构如下
for a in A():
for b in B(a):
for c in C(b):
foo(a,b,c)
Run Code Online (Sandbox Code Playgroud)
这种结构能用等效的itertools符号表示吗?
没有确切的itertools
解决方案,但简单的itertools
功能组合就足够了:
def chain_imap_accumulate(seq, f):
def acc_f(x):
for n in f(x[-1]):
yield x + (n,)
return chain.from_iterable(imap(acc_f, seq))
def accumulative_product(*generators):
head, tail = generators[0], generators[1:]
head = imap(tuple, head())
return reduce(chain_imap_accumulate, tail, head)
Run Code Online (Sandbox Code Playgroud)
快速测试.定义:
from itertools import chain, imap, izip
chain_ = chain.from_iterable
def A():
yield 'A'
yield 'B'
def B(x):
yield int(x, 16)
yield int(x, 16) + 1
def C(x):
yield str(x) + 'Z'
yield str(x) + 'Y'
Run Code Online (Sandbox Code Playgroud)
结果如下:
>>> list(accumulative_product(A, B, C))
[('A', 10, '10Z'), ('A', 10, '10Y'),
('A', 11, '11Z'), ('A', 11, '11Y'),
('B', 11, '11Z'), ('B', 11, '11Y'),
('B', 12, '12Z'), ('B', 12, '12Y')]
Run Code Online (Sandbox Code Playgroud)
几乎所有的复杂性都来自于输入的积累,正如上面代码的快速"推导"所示.在最终(c
)值可以使用只是几个嵌套来生成itertools
构建体:
>>> list(chain_(imap(C, chain_(imap(B, (A()))))))
['10Z', '10Y', '11Z', '11Y', '11Z', '11Y', '12Z', '12Y']
Run Code Online (Sandbox Code Playgroud)
这可以概括为reduce
.要使用reduce
,chain_imap
不能使用标准imap
参数顺序.它必须被交换:
def chain_imap(seq, f):
return chain.from_iterable(imap(f, seq))
Run Code Online (Sandbox Code Playgroud)
这给出了相同的结果:
>>> list(reduce(chain_imap, [B, C], A()))
['10Z', '10Y', '11Z', '11Y', '11Z', '11Y', '12Z', '12Y']
Run Code Online (Sandbox Code Playgroud)
最后的任务是积累的初始值,让你有机会获得a
,b
和c
.这需要一点思想得到正确,但执行是相当简单-我们只需要转换f
成忽略所有的输入值,但是最后的一个功能,并追加新值全情投入:
def chain_imap_accumulate(seq, f):
def acc_f(x):
for n in f(x[-1]):
yield x + (n,)
return chain.from_iterable(imap(acc_f, seq))
Run Code Online (Sandbox Code Playgroud)
这就需要首先输入被包裹在元组,所以我们映射A
有tuple
:
>>> list(reduce(chain_imap_accumulate, [B, C], imap(tuple, A())))
[('A', 10, '10Z'), ('A', 10, '10Y'),
('A', 11, '11Z'), ('A', 11, '11Y'),
('B', 11, '11Z'), ('B', 11, '11Y'),
('B', 12, '12Z'), ('B', 12, '12Y')]
Run Code Online (Sandbox Code Playgroud)
为清晰起见,重写上述内容,并在此答案的顶部显示代码.
顺便说一下,chain_imap_accumulate
使用genex可以更简洁地重写一下.这可以与较短版本结合使用,accumulative_product
以获得非常紧凑的定义(如果您对此类内容感兴趣).这也恰好完全消除了itertools依赖:
def chain_map_accumulate(seq, f):
return (x + (n,) for x in seq for n in f(x[-1]))
def accumulative_product2(*gens):
return reduce(chain_map_accumulate, gens[1:], (tuple(x) for x in gens[0]()))
Run Code Online (Sandbox Code Playgroud)
没有,但你可以制作一个:
def chainGang(steps, currentVars=None):
thisOne = steps[0]
if currentVars is None:
for item in thisOne():
for gang in chainGang(steps[1:], [item]):
yield gang
elif len(steps) == 1:
for item in thisOne(currentVars[-1]):
yield currentVars + [item]
else:
for item in thisOne(currentVars[-1]):
for gang in chainGang(steps[1:], currentVars + [item]):
yield gang
Run Code Online (Sandbox Code Playgroud)
进而:
>>> outer = lambda: ["A", "B", "C", "D"]
>>> middle = lambda letter: [letter, letter*2, letter*3]
>>> inner = lambda s: range(len(s)+1)
>>> for a in chainGang([outer, middle, inner]):
... print a
[u'A', u'A', 0]
[u'A', u'A', 1]
[u'A', u'AA', 0]
[u'A', u'AA', 1]
[u'A', u'AA', 2]
[u'A', u'AAA', 0]
[u'A', u'AAA', 1]
[u'A', u'AAA', 2]
[u'A', u'AAA', 3]
[u'B', u'B', 0]
[u'B', u'B', 1]
[u'B', u'BB', 0]
[u'B', u'BB', 1]
[u'B', u'BB', 2]
[u'B', u'BBB', 0]
[u'B', u'BBB', 1]
[u'B', u'BBB', 2]
[u'B', u'BBB', 3]
[u'C', u'C', 0]
[u'C', u'C', 1]
[u'C', u'CC', 0]
[u'C', u'CC', 1]
[u'C', u'CC', 2]
[u'C', u'CCC', 0]
[u'C', u'CCC', 1]
[u'C', u'CCC', 2]
[u'C', u'CCC', 3]
[u'D', u'D', 0]
[u'D', u'D', 1]
[u'D', u'DD', 0]
[u'D', u'DD', 1]
[u'D', u'DD', 2]
[u'D', u'DDD', 0]
[u'D', u'DDD', 1]
[u'D', u'DDD', 2]
[u'D', u'DDD', 3]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1610 次 |
最近记录: |