按顺序对列表中的元素进行分组

时间:2015-03-25 12:05:34

标签: python list grouping

我是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']

3 个答案:

答案 0 :(得分: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 :(得分: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']]

答案 2 :(得分: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']]

如果您想要存储,那么您可以通过名称访问使用dict:

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