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

Python 按顺序对列表中的元素进行分组,python,list,grouping,Python,List,Grouping,我是python新手。有一项复杂的任务要做 我有一个文本文件,其中包含由注释和命令分隔的部分。文件中有多个部分。我想提取与它自己的部分相关的命令,并从中创建一个列表 示例: 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

我是python新手。有一项复杂的任务要做

我有一个文本文件,其中包含由注释和命令分隔的部分。文件中有多个部分。我想提取与它自己的部分相关的命令,并从中创建一个列表

示例:

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

您的问题是一个简单的分组练习,它可以通过跟踪一个节的开始来实现,以指示后续行应该附加到一个新列表中

实施

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']]
使用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.imap
itertools.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']}

您可以创建一个最初为空的节列表。每次找到以
#
开头的行时,都会附加一个子列表。否则,如果到目前为止遇到一个节,并且该行不是空的,则将该行添加到最后插入的
节的子列表中

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

嗨,欢迎来到StackOverflow!你还没有问过一个问题,那么你在努力完成任务的哪一部分呢?最好是展示您迄今为止编写的代码,并解释它如何没有达到您期望的效果。那么我们就有可能找出它的毛病了。谢谢蒂姆。这是以前的代码,我正在根据这里的人提供的输入修改它。def extract(self,outfile,mode):f=self中c的open(outfile,mode)。内容:如果不是c.startswith(“#”):commands=c.rstrip()#f.write(commands+'\n')self.clist.append(commands)f.close()我会纠正它…但即使你用一个衬垫…我认为它太大了,不能放在一个衬垫里line@JuniorCompressor,它符合pep8,并给出正确的答案,因此否决票仍然非常有趣。@JUnitorCompressor,您必须记住程序员是懒惰的;)