列出python中的理解行为 [英] List comprehension behavior in python

查看:68
本文介绍了列出python中的理解行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与Codeskulptor合作解决岩石碰撞问题.我想检查一下岩石之间的碰撞,我的岩石在列表中.我想出了解决方案,以建立组合列表,然后检查碰撞. 我没有可用的itertools. 我的组合列表是这样创建的:

I am working with Codeskulptor on a rock collision problem. I want to check collisions between rocks and my rocks are in a list. I came up with the solution to build a list of combinations and then check for collision. I do not have itertools available. My combination list was created like this:

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')] 

结果还可以.

我以前尝试过使用以下功能实现此功能:

I tried to do this in a one liner before with functions:

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)

但是结果是完全不同和错误的:

But the outcome is completely different and wrong:

[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'B'), ('B', 'D'), ('C', 'C'), ('C', 'D'), ('D', 'D')]

列表理解对我来说还是个小魔咒.我无法解释这种行为,但是想了解错误的出处. 我知道我的两行解决方案要快得多,因为枚举只完成一次,而不是使用一次.但是错误的输出对我来说是无法解释的,尤其是当BC丢失并且BB CC DD翻倍而AA丢失时.

List comprehension is still a little black magic to me. I cannot explain this behavior, would like to understand the wrong out though. I know that my two line solution is much faster, since enumerate is only done once and than used. But the wrong output is unexplainable to me, especially as BC is missing and BB CC DD doubles are there while AA is missing.

有人可以帮助我吗?

推荐答案

了解列表理解时,要做的第一件事是将其扩展为常规的for循环集.从左到右读取循环并进行相应的嵌套.

First thing to do when understanding a list comprehension is to expand it to a regular set of for loops. Read the loops from left to right and nest accordingly.

工作代码:

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

并且您的尝试无效:

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

也许通过这种方式,可以更容易地看到两个版本之间出了什么问题.

Perhaps this way it is easier to see what goes wrong between the two versions.

您的版本切片恰好 items,而不是> 生成的索引.原始版本将[(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D')]切片为[(1, 'B'), (2, 'C'), (3, 'D')]等,而您的版本将切片重新编号为[(0, 'B'), (1, 'C'), (2, 'D')].这反过来会导致您的输出错误.

Your version slices just items, not the indices produced by enumerate(). The original version slices [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D')] down to [(1, 'B'), (2, 'C'), (3, 'D')], etc. while your version re-numbers that slice to [(0, 'B'), (1, 'C'), (2, 'D')]. This in turn leads to your erroneous output.

通过向enumerate()函数添加第二个参数(从此处开始编号的索引),在较高的索引处开始内部循环:

Start the inner loop at the higher index by adding a second argument to the enumerate() function, the index at which to start numbering:

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

返回单线:

def combinations2(items):
    return [(item, item2) for n, item in enumerate(items) for m, item2 in enumerate(items[n:], n) if n != m]

然后可以正常工作:

>>> 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')]

请注意,您可以进一步简化 n == mTrue的唯一时间是每个内部循环的第一次迭代.只需将items列表切为内部列表一个值进一步;从1开始将外部enumerate()放下,将内部enumerate()放下,然后将n != m测试放下:

Note that you can simplify it further; the only time when n == m is True is for the first iteration of each inner loop. Just slice the items list for the inner list one value further; start the outer enumerate() at 1, drop the inner enumerate() and drop the n != m test:

def combinations3(items):
    result = []
    for n, item in enumerate(items, 1):
        for item2 in items[n:]:
            result.append((item, item2))
    return result

或作为列表理解:

def combinations3(items):
    return [(item, item2) for n, item in enumerate(items, 1) for item2 in items[n:]]

这篇关于列出python中的理解行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆