2013-07-08 2 views
0

Я работаю с сетевой библиотекой, которая возвращает генератор, где вы получаете произвольное количество текста (в виде строки) с каждым вызовом Next(); где, если вы просто конкатенируете результат каждого вызова Next(); будет выглядеть как стандартный текстовый документ на английском языке.Есть ли генератор, который превратит поток текста в поток строк?

В строке, возвращаемой каждым вызовом Next(), может быть несколько строк новой строки, их может не быть. Возвращенная строка не обязательно заканчивается символом новой строки, т. Е. Одна строка текста может быть разнесена по нескольким вызовам Next().

Я пытаюсь использовать эти данные во второй библиотеке, которая нуждается в Next(), чтобы вернуть одну строку текста. Это абсолютно важно, я не читаю во всем потоке; это может быть десятки гигабайт данных.

Есть ли встроенная библиотека для решения этой проблемы? Если нет, может ли кто-нибудь предложить лучший способ написать генератор или альтернативный способ решить проблему?

+0

, не зная ничего о структуре входящего текста, на это довольно сложно ответить. Пожалуйста, добавьте еще к вашему вопросу – inspectorG4dget

+0

Действительно ли имеет значение структура текста? Это куча текстовых данных с новыми символами. Генератор возвращает строки. – Chuu

+0

Можете ли вы построить свой собственный, используя 'для строки в stream.split ('\ n'): yield line'? – wflynny

ответ

2

Напишите функцию генератора, которая тянет куски и разбивает их на линии для вас. Поскольку вы не знаете, закончилась ли последняя строка в новой строке или нет, сохраните ее и присоедините к следующему фрагменту.

def split_by_lines(text_generator): 
    last_line = "" 
    try: 
     while True: 
      chunk = "".join(last_line, next(text_generator)) 
      chunk_by_line = chunk.split('\n') 
      last_line = chunk_by_line.pop() 
      for line in chunk_by_line: 
       yield line 
    except StopIteration: # the other end of the pipe is empty 
     yield last_line 
     raise StopIteration 
+0

В Python 2.4 это требует некоторых небольших изменений, так как перегрузка .join и next (...) еще не существовала. – Chuu

0

После прочтения вашего редактирования, возможно, вы можете изменить объект потока, который возвращает произвольное количество текста? Например, в методе stream.next() существует некоторый способ, которым поток генерирует строку и yields, когда вызывается .next(). Не могли бы вы сделать что-то вроде:

def next(self): 
    if '\n' in self.remaining: 
     terms = self.remaining.split('\n') 
     to_yield, self.remaining = terms[0], ''.join(terms[1:]) 
     yield to_yield 
    else: 
     to_yield = self.remaining + self.generate_arbitrary_string() 
     while '\n' not in to_yield: 
      to_yield += self.generate_arbitrary_string() 
     to_yield, self.remaining = terms[0], ''.join(terms[1:]) 
     yield to_yield   

Это псевдокод предполагает, что объект потока создает некоторую произвольную строку с generate_arbitrary_string(). При первом вызове next() строка self.remaining должна быть пустой, поэтому вы переходите к оператору else. Там вы конкатенируете произвольные строки, пока не найдете символ newline, разделите конкатенированную строку на первый символ newline, дайте первую половину и сохраните вторую половину в remaining.

При последующих звонках next() вы сначала проверяете, содержит ли self.remaining любые newline символов. Если это так, выведите первую строку и сохраните остальные. Если нет, добавьте новую произвольную строку в self.remaining и продолжайте, как указано выше.