Извлечение строк ниже категории и остановка при достижении другой категории - PullRequest
1 голос
/ 10 ноября 2010

Предположим, у меня есть текстовый файл жанров фильмов с моими любимыми фильмами под каждый жанр.

[категория] Ужасы:

  1. Фильм
  2. Фильм
  3. Фильм

[категория] комедия:

  1. Фильм

[категория] Действие:

  1. Фильм
  2. Видео

Как бы я создал функцию, которая извлекает и упаковывает все заголовки фильмов ниже определенной [категории] * в массив, не перетекая в другую категорию?

Ответы [ 4 ]

2 голосов
/ 10 ноября 2010

Вы можете разбирать файл построчно следующим образом:

import collections

result=collections.defaultdict(list)
with open('data') as f:
    genre='unknown'
    for line in f:
        line=line.strip()
        if line.startswith('[category]'):
            genre=line.replace('[category]','',1)
        elif line:
            result[genre].append(line)

for key in result:
    print('{k} {m}'.format(k=key,m=list(result[key])))

приводит к

 Action: ['1. Movie', '2. Movie']
 Comedy: ['1. Movie']
 Horror: ['1. Movie', '2. Movie', '3. Movie']
2 голосов
/ 10 ноября 2010

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

[Horror]
1: Movie
2: Movie
3: Movie

[Comedy]
1: Movie

[Action]
1: Movie
2: Movie
1 голос
/ 10 ноября 2010

Использование отрицательного взгляда :

\[category\](?:(?!\[category\]).)*

будет соответствовать одной целой категории (если регулярное выражение составлено с использованием параметра re.DOTALL).

Вы можетезахватите категорию и содержание отдельно, используя

\[category\]\s*([^\r\n]*)\r?\n((?:(?!\[category\]).)*)

После матча mymatch.group(1) будет содержать категорию, а mymatch.group(2) будет содержать названия фильмов.

Пример в Python 3.1(используя вашу строку как mymovies):

>>> import re
>>> myregex = re.compile(r"\[category\]\s*([^\r\n]*)\r?\n((?:(?!\[category\]).)*)", re.DOTALL)
>>> for mymatch in myregex.finditer(mymovies):
...     print("Category: {}".format(mymatch.group(1)))
...     for movie in mymatch.group(2).split("\n"):
...         if movie.strip():
...              print("contains: {}".format(movie.strip()))
...
Category: Horror:
contains: 1. Movie
contains: 2. Movie
contains: 3. Movie
Category: Comedy:
contains: 1. Movie
Category: Action:
contains: 1. Movie
contains: 2. Movie
>>>
0 голосов
/ 10 ноября 2010
import re

re_cat = re.compile("\[category\] (.*):")

categories = {}

category = None

for line in open("movies.txt", "r").read().split("\n"):
    line = line.strip()
    if not line:
        continue
    if re_cat.match(line):
        category = re_cat.sub("\\1", line)
        if not category in categories:
            categories[category] = []
 continue
    categories[category].append(line)

print categories

Создает следующий словарь:

{
'Action': ['Movie', 'Movie'],
'Horror': ['Movie', 'Movie', 'Movie'],
'Comedy': ['Movie']
}

Мы используем одно и то же регулярное выражение для сопоставления и вычеркивания имени категории, поэтому эффективно скомпилировать его с re.compile.

У нас есть переменная category, которая изменяется при каждом анализе новой категории.Любая строка, которая не определяет новую категорию, добавляется в словарь categories под соответствующим ключом.Категории, определенные впервые, создают список под правой клавишей словаря, но категории также могут быть перечислены несколько раз, и все будет заканчиваться правой клавишей.

Любые фильмы, перечисленные до определения категории, будут всловарь под ключом None.

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