Могу ли я использовать itertools.groupby для возврата групп строк, где первая строка начинается с определенного символа? - PullRequest
0 голосов
/ 19 мая 2019

У меня есть текстовый файл, который выглядит так:

> Начало группы

text1

text2

> Начало новой группы

text3

Я пытался использовать 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, поскольку я впервые пытаюсь ее реализовать, поэтому любое объяснение приветствуется.

Ответы [ 3 ]

2 голосов
/ 19 мая 2019

Вот способ получить ваши данные без функции группировки.

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

data = []

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

    if line.startswith('>'):
        data.append([line])
    else:
        data[-1].append(line)
0 голосов
/ 20 мая 2019

Ключ заключается в том, чтобы пометить каждую строку в той же группе одним и тем же номером, что можно сделать с помощью другого генератора.Считайте это демонстрацией того, как работает groupby, а не практическим предложением;вместо этого используйте ответ Криса Чарли.

def number_lines(txt):
    i = 0
    for line in text:
        if line.startswith(">"):
            i += 1
        yield (1, line)

Обратите внимание, что последовательность кортежей, создаваемая number_lines, автоматически сортируется по первому элементу кортежа.Чтобы сгруппировать их, скажите groupby, чтобы использовать первый элемент в качестве «группового тега».

from operator import itemgetter

with open(filename) as rfile:
    numbered_lines = number(rfile)
    groups = [[line for n, line in group]
              for number, group in groupby(numbered_lines, itemgetter(0))]
0 голосов
/ 20 мая 2019

groupby группирует элементы в итерируемом по некоторому предикату, который применяется к каждому элементу.Это означает, что предикат группировки должен быть в состоянии идентифицировать группируемый объект, рассматривая только один элемент.Поскольку ваши данные не позволяют (вы должны посмотреть на предыдущие элементы, чтобы определить ключ группировки), это не является хорошим кандидатом для использования groupby, и ответ Криса Чарли является более чистым решением.

Тем не менееЕсли вы рассматриваете это как проблему кодирования, а не как реальную проблему, вы можете создать функцию группировки, которая хранит состояние и отслеживает последнюю увиденную метку группы.Класс, который реализует __call__ и хранит последнюю метку группы, замеченную как свойство, и возвращает, что, когда следующий вход не является меткой группы, может достичь того, что вы ищете.

...