2015-04-21 15 views
1

我已經寫了一些代碼,並試圖理解列表推導的概念,我試圖將一些代碼轉換爲列表解析。幾個列表解析 - 一個接一個

我有一個嵌套的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 = ...」部分工作正常,如果它是第一個列表理解,但不是如果它是第二個。與上述相同 - 如果它是第一個,它似乎只能起作用。爲什麼是這樣?

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

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

回答

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) 

基本上,你只是「扁平化」的該塊代碼並將其添加到前面。

+0

這很有道理,@tobias_k。您的答案已經過測試,並且可行!謝謝。 – Hjalte

+0

您能否簡單介紹一下上述嵌套列表理解的工作原理? – Hjalte