几个列表理解 - 一个接一个

时间:2015-04-21 08:30:39

标签: python for-loop list-comprehension

我已经编写了一些代码,并试图掌握列表推导的概念,我试图将一些代码转换为列表推导。

我有一个嵌套的for循环:

with (Input) as searchfile:
    for line in searchfile:
        if '*' in line:
            ID = line[2:13]
            IDstr = ID.strip()
            print IDstr
            hit = line
            for i, x in enumerate(hit):
                    if x=='*':
                      position.append(i)
                      print position

我已将代码的第一部分变为列表理解:

ID = [line[2:13].strip() for line in Input if '*' in line]
print ID

这很好用。我试图做下一个,但它没有按预期工作。如何在彼此之后进行多次列表推导。如果它是第一个列表理解,下面的“命中= ...” - 部分工作正常,但如果是第二个则不行。与上述相同 - 它似乎只是工作,如果它是第一个。这是为什么?

Hit = [line for line in Input if '*' in line]
print Hit

Positions = [(i, x) for i, x in enumerate(Hit) if x == '*']
print Positions

1 个答案:

答案 0 :(得分:2)

  

它似乎只是工作,如果它是第一个。这是为什么?

这是因为file对象 - 在你的情况下是input - 是迭代器,即一旦你迭代它们就会耗尽它们。在for循环中,这不是问题,因为您只为IDposition迭代文件一次。如果你想使用这样的两个列表推导,你要么必须为第二个重新打开文件,要么将文件中的行读入列表,并在列表推导中使用该列表。

另请注意,您的positions列表理解是错误的,因为它列举了Hit列表,而不是列表中的每个元素,就像在你的循环。

您可以尝试这样(未经测试):

# first, get the lines with '*' just once, cached as a list
star_lines = [line for line in input if '*' in line]
# now get the IDs using those cached lines
ids = [line[2:13].strip() for line in star_lines]
# for the positions we need a nested list comprehension
positions = [i for line in star_lines for i, x in enumerate(line) if x == '*']

嵌套列表推导与这个嵌套循环相当:

positions = []
for line in star_lines:
    for i, x in enumerate(line):
        if x == '*':
            posiitons.append(i)

基本上,你只是"压扁"那段代码并把东西放在前面。