2015-03-25 51 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']]