Питон: предмет для предмета, пока не остановится в предмете? - PullRequest
3 голосов
/ 03 декабря 2008

Отказ от ответственности: я довольно плохо знаком с Python!

Если я хочу, чтобы все строки файла были до (отредактированы и включая) строки, содержащей некоторую строку stopterm, есть ли способ использовать для этого синтаксис списка? Я надеялся, что будет что-то вроде:

usefullines = [line for line in file until stopterm in line]

Пока у меня есть

usefullines = []
for line in file:
    usefullines.append(line)
    if stopterm in line:
        break

Это не конец света, но так как остальная часть синтаксиса Python настолько проста, я надеялся на отображение строки с 1 мыслью-> 1 Python.

Ответы [ 6 ]

10 голосов
/ 03 декабря 2008
from itertools import takewhile
usefullines = takewhile(lambda x: not re.search(stopterm, x), lines)

from itertools import takewhile
usefullines = takewhile(lambda x: stopterm not in x, lines)

Вот способ удержания линии остановки:

def useful_lines(lines, stopterm):
    for line in lines:
        if stopterm in line:
            yield line
            break
        yield line

usefullines = useful_lines(lines, stopterm)
# or...
for line in useful_lines(lines, stopterm):
    # ... do stuff
    pass
5 голосов
/ 03 декабря 2008

«Я надеялся на отображение 1 Python-> 1 Python». Разве мы все не любим язык программирования, который каким-то образом отражает наш естественный язык?

Вы можете достичь этого, вам просто нужно определить свои уникальные мысли один раз. Тогда у вас есть отображение 1: 1, на которое вы рассчитывали.

def usefulLines( aFile ):
    for line in aFile:
        yield line
        if line == stopterm:
            break

В значительной степени это.

for line in usefulLines( aFile ):
    # process a line, knowing it occurs BEFORE stopterm.

Есть более общие подходы. Ответы lassevk с enum_while и enum_until являются обобщениями этого простого шаблона проектирования.

2 голосов
/ 03 декабря 2008

Это решение itertools аккуратно. Ранее я был поражен itertools.groupby, одним удобным инструментом.

Но все же я просто возился, если бы мог сделать это без itertools. Так вот (Есть одно предположение и один недостаток: файл не очень большой, и он проходит одну дополнительную полную итерацию по строкам соответственно.)

Я создал пример файла с именем "try":

hello
world
happy
day
bye

после прочтения файла и появления строк в имени переменной:

lines=open('./try').readlines()

тогда

    print [each for each in lines if lines.index(each)<=[lines.index(line) for line in lines if 'happy' in line][0]]

дает результат:

['hello\n', 'world\n', 'happy\n']

и

print [each for each in lines if lines.index(each)<=[lines.index(line) for line in lines if 'day' in line][0]]

дает результат:

['hello\n', 'world\n', 'happy\n', 'day\n']

Итак, вы получили последнюю строку - также включена строка с условием остановки.

1 голос
/ 03 декабря 2008

Я думаю, что это нормально. Сложные однострочники на самом деле не питонны, и, поскольку Гвидо должен был где-то установить предел, я думаю, что это оно ...

1 голос
/ 03 декабря 2008

Забудь об этом

Оставляя ответ, но отмечая его сообществом. См. Stewen Huwig ответ для правильного способа сделать это.


Что ж, [x для x в enumerable] будет работать до тех пор, пока enumerable больше не выдаст данные, а if-part просто позволит вам выполнить фильтрацию по пути.

Что вы можете сделать, это добавить функцию и отфильтровать ее через нее:

def enum_until(source, until_criteria):
    for k in source:
        if until_criteria(k):
            break;
        yield k;

def enum_while(source, while_criteria):
    for k in source:
        if not while_criteria(k):
            break;
        yield k;

l1 = [k for k in enum_until(xrange(1, 100000), lambda y: y == 100)];
l2 = [k for k in enum_while(xrange(1, 100000), lambda y: y < 100)];
print l1;
print l2;

Конечно, это выглядит не так хорошо, как вы хотели ...

0 голосов
/ 03 декабря 2008

Я бы пошел с Стивеном Хувигом или С.Лоттом решениями для реального использования, но в качестве слегка хакерского решения, вот один из способов получить это поведение:

def stop(): raise StopIteration()

usefullines = list(stop() if stopterm in line else line for line in file)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...