2015-03-25 36 views
2

我是python的新手。有一個複雜的任務工作。按順序排列列表中的元素

我有一個文本文件,其中包含由註釋分隔的部分,命令在它們之間。文件中有多個部分。我想提取與它自己的部分相關的命令並從中創建一個列表。

Eample:

test.txt 

#section 1 
ls -1 
sudo apt-get install vim 

#section 2 
sudo apt-get install ruby 

輸出:

list1 = ['ls -1','sudo apt-get install vim'] 
list2 = ['sudo apt-get install ruby'] 
+4

您好,歡迎計算器!你實際上沒有問過一個問題,那麼你正在努力完成哪部分任務?如果你展示你迄今爲止編寫的代碼,並解釋它不是在做你期望的代碼,那也許是最好的。那麼我們有可能找出它有什麼問題。 – 2015-03-25 12:07:58

+0

謝謝蒂姆。 這是以前的代碼,我正在修改它基於這裏的人給出的輸入。 DEF提取物(自,OUTFILE,模式): F =開放(OUTFILE,模式) 對於C在self.contents: 如果不是c.startswith( 「#」): 命令= c.rstrip() #f.write(commands +'\ n') self.clist.append(commands) f。關閉() – 2015-03-25 15:10:32

回答

2

你的問題是一個簡單的分組練習,這可以簡單地通過跟蹤部分開始的指示,隨後的線應該是可以實現追加到新清單

執行

output = [[]] 
with open("test.txt") as fin: 
    #from itertools import imap 
    for line in map(str.strip, fin): 
    #for line in imap(str.strip, fin): 
     if line: 
      if line.startswith('#'): 
       output.append([]) 
       continue 
      output[-1].append(line) 
    output = output[1:] 

假設你的文件包含

test.txt 

#section 1 
ls -1 
sudo apt-get install vim 

#section 2 
ls -lrt 
sudo apt-get install ruby 

輸出

[['ls -1', 'sudo apt-get install vim'], ['ls -lrt', 'sudo apt-get install ruby']] 
1

使用GROUPBY:

from itertools import groupby 

with open("test.txt") as f: 
    for k, v in groupby(map(str.strip, f), lambda x: not x.startswith("#")): 
     if k: 
      print(list(filter(None, v))) 
['ls -1', 'sudo apt-get install vim'] 
['sudo apt-get install ruby'] 

對於python2使用itertools.imapitertools.ifilter

您可以創建一個列表的列表與列表理解:

from itertools import groupby 
with open("test.txt") as f: 
    out = [list(filter(None, v)) for k, v in groupby(map(str.strip, f), lambda x: not x.startswith("#")) if k] 
print(out) 
['ls -1', 'sudo apt-get install vim'], ['sudo apt-get install ruby']] 

如果你想然後保存,所以你可以按名稱訪問使用的字典:

from itertools import groupby 
from itertools import count 
with open("test.txt") as f: 
    d = {} 
    cn = count(1) 
    for k, v in groupby(map(str.strip, f), lambda x: not x.startswith("#")): 
     if k: 
      d["list_{}".format(next(cn))] = list(filter(None, v)) 

print(d) 
{'list_2': ['sudo apt-get install ruby'], 'list_1': ['ls -1', 'sudo apt-get install vim']} 
+0

有趣的downvote爲一個正確的答案 – 2015-03-25 12:44:48

+0

我會糾正它......但即使你使用單線......我認爲這是太大,不能保持在一行 – JuniorCompressor 2015-03-25 12:45:32

+0

@JuniorCompressor,它符合pep8和產生正確的答案,所以downvote仍然很有趣。 – 2015-03-25 12:48:15

2

你可以創建一個最初爲空的部分列表。每當您找到以#開頭的行時,您都會追加一個子列表。否則,如果我們到目前爲止遇到一個部分並且該行不是空的,我們將該行添加到最後插入的子列表sections

sections = [] 
with open("test.txt", "r") as f: 
    for line in map(str.strip, f): 
     if line.startswith('#'): 
      sections.append([]) 
     elif sections and line: 
      sections[-1].append(line) 

結果:

[['ls -1', 'sudo apt-get install vim'], ['sudo apt-get install ruby']]