Python 我可以使用itertools.groupby返回第一行以特定字符开头的行组吗?

Python 我可以使用itertools.groupby返回第一行以特定字符开头的行组吗?,python,group-by,itertools,fileparsing,Python,Group By,Itertools,Fileparsing,我有一个如下所示的文本文件: [['>Start of group'],[text1],[text2],['>Start of new group'],[text3]] >小组开始 文本1 文本2 >新组的开始 文本3 我一直在尝试使用itertools.groupby返回组,其中每个组都是包含以下内容的列表列表: 1) 以“>”字符开头的行 2) 以“>”字符开头的行之后的文本行,直到以“>”字符开头的下一行 因此,从前面的文本中,我想得到: [['>Start of gr

我有一个如下所示的文本文件:

[['>Start of group'],[text1],[text2],['>Start of new group'],[text3]]
>小组开始

文本1

文本2

>新组的开始

文本3


我一直在尝试使用
itertools.groupby
返回组,其中每个组都是包含以下内容的列表列表:

1) 以“>”字符开头的行

2) 以“>”字符开头的行之后的文本行,直到以“>”字符开头的下一行

因此,从前面的文本中,我想得到:

[['>Start of group', text1, text2], ['>Start of new group', text3]]
到目前为止,我编写的代码是:

with open(filename) as rfile:
    groups = []

    for key, group in groupby(rfile, lambda x: x.startswith(">")):
        groups.append(list(group))
但是,这将生成一个列表列表,其中文件的每一行都位于其自己的列表中,如下所示:

[['>Start of group'],[text1],[text2],['>Start of new group'],[text3]]

我想我可能只是不太理解groupby函数,因为这是我第一次尝试实现它,所以任何解释都非常感谢。

下面是一种不用groupby函数获取数据的方法

fin = open('fasta.out', 'r')

data = []

for line in fin:
    line = line.rstrip()

    if line.startswith('>'):
        data.append([line])
    else:
        data[-1].append(line)

下面是一种不使用groupby函数获取数据的方法

fin = open('fasta.out', 'r')

data = []

for line in fin:
    line = line.rstrip()

    if line.startswith('>'):
        data.append([line])
    else:
        data[-1].append(line)

groupby
通过应用于每个元素的某个谓词对iterable中的项进行分组。这意味着分组谓词必须能够通过只查看一个元素来识别正在分组的特征。由于您的数据不允许(您必须查看前面的元素以确定分组键),因此这不是使用
groupby
的好选择,Chris Charley的答案是一个更干净的解决方案


也就是说,如果您将此视为编码挑战而不是解决实际问题,则可以创建一个分组函数,用于存储状态并跟踪最后看到的组标签。一个类,它实现了
\uuuuu call\uuuuuu
,并将最后一个组标签存储为属性,并返回当下一个输入不是组标签时,可以实现所需的功能。

groupby
通过应用于每个元素的某个谓词对iterable中的项进行分组。这意味着分组谓词必须能够通过只查看一个元素来识别正在分组的特征。由于您的数据不允许(您必须查看前面的元素以确定分组键),因此这不是使用
groupby
的好选择,Chris Charley的答案是一个更干净的解决方案


也就是说,如果您将此视为编码挑战而不是解决实际问题,则可以创建一个分组函数,用于存储状态并跟踪最后看到的组标签。一个类,它实现了
\uuuuu call\uuuuuu
,并将最后一个组标签存储为属性,并返回当下一个输入不是组标签时,可以实现您想要的功能。

关键是用相同的数字标记同一组中的每一行,这可以用另一个生成器完成。考虑这是一个演示如何<代码> GROPBY <代码>工作,而不是一个实际的建议;用克里斯·查利的答案代替

def number_lines(txt):
    i = 0
    for line in text:
        if line.startswith(">"):
            i += 1
        yield (1, line)
请注意,
number\u lines
生成的元组序列会根据元组的第一个元素自动排序。要对它们进行分组,请告诉
groupby
使用第一个元素作为“组标记”


关键是用相同的编号标记同一组中的每一行,这可以用另一个生成器完成。考虑这是一个演示如何<代码> GROPBY <代码>工作,而不是一个实际的建议;用克里斯·查利的答案代替

def number_lines(txt):
    i = 0
    for line in text:
        if line.startswith(">"):
            i += 1
        yield (1, line)
请注意,
number\u lines
生成的元组序列会根据元组的第一个元素自动排序。要对它们进行分组,请告诉
groupby
使用第一个元素作为“组标记”


稍微干净一点:
if line.startswith('>'):data.append([]);数据[-1].append(line)
。稍微清理一下:
如果line.startswith('>'):data.append([]);数据[-1]。追加(行)
itertools。groupby
具有具有共同特征的项目组,例如,将所有大写字母分组,将所有以“foo”开头的单词分组。在这里使用它会更困难,因为您实际上只想在某些条件之前分割字符串。请参见此处的
itertools。groupby
包含具有共同特征的项目组,例如,将所有大写字母分组,将所有以“foo”开头的单词分组。在这里使用它会更困难,因为您实际上只想在某些条件之前分割字符串。看到这里了吗