Joh*_*ank 0 python list-comprehension enumerate
我正在与Codeskulptor合作解决岩石碰撞问题.我想检查岩石之间的碰撞,我的岩石列在清单中.我想出了构建组合列表然后检查碰撞的解决方案.我没有itertools可用.我的组合列表是这样创建的:
def combinations(items):
n_items = [(n,item) for n,item in enumerate(items)]
return [(item,item2) for n,item in n_items for m,item2 in n_items[n:] if n != m]
letters = ['A','B','C','D']
print combinations(letters)
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
Run Code Online (Sandbox Code Playgroud)
结果还可以.
在尝试使用函数之前,我尝试在一个衬里中执行此操作:
def combinations2(items):
return [(item,item2) for n,item in enumerate(items) for m,item2 in enumerate(items[n:]) if n != m]
letters = ['A','B','C','D']
print combinations2(letters)
Run Code Online (Sandbox Code Playgroud)
但结果是完全不同和错误的:
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'B'), ('B', 'D'), ('C', 'C'), ('C', 'D'), ('D', 'D')]
Run Code Online (Sandbox Code Playgroud)
列表理解对我来说仍然是一个黑魔法.我无法解释这种行为,想了解错误了.我知道我的双线解决方案要快得多,因为枚举只执行一次而不是使用.但错误的输出对我来说是无法解释的,特别是当BC丢失并且BB CC DD加倍时,AA缺失.
有人能帮我吗?
理解列表理解时要做的第一件事是将其扩展为常规的for循环集.从左到右阅读循环并相应地嵌套.
工作代码:
def combinations(items):
n_items = []
for n,item in enumerate(items):
n_items.append((n,item))
result = []
for n, item in n_items:
for m, item2 in n_items[n:]:
if n != m:
result.append((item, item2))
return result
Run Code Online (Sandbox Code Playgroud)
而你的尝试不起作用:
def combinations2(items):
result = []
for n, item in enumerate(items):
for m, item2 in enumerate(items[n:]):
if n != m:
result.append((item, item2))
return result
Run Code Online (Sandbox Code Playgroud)
也许这样就可以更容易地看出两个版本之间出了什么问题.
你的版本只是 切片items,而不是生成的索引enumerate().当您的版本重新编号切片[(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D')]时[(1, 'B'), (2, 'C'), (3, 'D')],原始版本会切换到等[(0, 'B'), (1, 'C'), (2, 'D')].这反过来会导致错误的输出.
通过向enumerate()函数添加第二个参数来启动较高索引的内部循环,该函数是开始编号的索引:
def combinations2(items):
result = []
for n, item in enumerate(items):
for m, item2 in enumerate(items[n:], n):
if n != m:
result.append((item, item2))
return result
Run Code Online (Sandbox Code Playgroud)
回到单线:
def combinations2(items):
return [(item, item2) for n, item in enumerate(items) for m, item2 in enumerate(items[n:], n) if n != m]
Run Code Online (Sandbox Code Playgroud)
这可以正常工作:
>>> def combinations2(items):
... return [(item, item2) for n, item in enumerate(items) for m, item2 in enumerate(items[n:], n) if n != m]
...
>>> letters = ['A','B','C','D']
>>> combinations2(letters)
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
Run Code Online (Sandbox Code Playgroud)
请注意,您可以进一步简化它; 唯一的时间n == m是True每个内循环的第一次迭代.只需items将内部列表的列表进一步切片一个值 ; 从外面开始enumerate()1,放下内部enumerate()并放弃n != m测试:
def combinations3(items):
result = []
for n, item in enumerate(items, 1):
for item2 in items[n:]:
result.append((item, item2))
return result
Run Code Online (Sandbox Code Playgroud)
或作为列表理解:
def combinations3(items):
return [(item, item2) for n, item in enumerate(items, 1) for item2 in items[n:]]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
102 次 |
| 最近记录: |