2010-11-10 18 views
1

Supposons que je possède un fichier texte de genres de films avec mes films préférés dans chaque genre.Extrayez les lignes sous la catégorie et arrêtez lorsqu'une autre catégorie est atteinte

[catégorie] Horreur:

  1. Film
  2. Film
  3. Film

[catégorie] Comédie:

  1. Film

[catégorie] Action:

  1. Film
  2. Film

Comment puis-je créer une fonction qui extrait et paquets tous les titles film ci-dessous une certaine [catégorie] * dans un tableau sans déborder dans une autre catégorie?

+0

Pouvez-vous re-marquer l'exemple de fichier texte en tant que "code" monospace? Les listes numérotées rendent difficile de voir quelle est la séquence exacte des caractères. –

+0

@Renzor - Veuillez fournir un exemple de code court pour savoir comment appeler cette fonction et ce que vous attendez en retour, par ex. 'myFavorite (Horror) renvoie [Movie, Movie, Movie]' – Theodor

Répondre

1

Utilisez un negative lookahead:

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

correspondra à une catégorie entière (si le regex est compilé avec l'option re.DOTALL).

Vous pouvez saisir la catégorie et le contenu séparément à l'aide

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

Après un match, mymatch.group(1) contiendra la catégorie et mymatch.group(2) contiendra les titres de films.

Exemple en Python 3.1 (en utilisant votre chaîne comme 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 
>>> 
2

Vous pouvez analyser la ligne par ligne fichier ainsi:

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]))) 

cède

Action: ['1. Movie', '2. Movie'] 
Comedy: ['1. Movie'] 
Horror: ['1. Movie', '2. Movie', '3. Movie'] 
+0

Hey, beaucoup plus agréable que d'utiliser une regex :) –

+0

Merci, @Tim. Votre solution regex est assez louche aussi. C'est agréable de voir une variété de solutions. – unutbu

2

Déjà donné le conseil des autres pour votre format de fichier texte, je suis juste en train de donner une autre suggestion ... Si la réécriture de votre fichier est possible, une solution facile pourrait être de changer à ConfigParser -readable (et écriture) Fichier:

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

[Comedy] 
1: Movie 

[Action] 
1: Movie 
2: Movie 
+0

Belle suggestion! Voici un lien vers la [documentation ConfigParser] (http://docs.python.org/library/configparser.html) pour plus de commodité. –

0
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 

Makes le dictionnaire suivant:

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

Nous utilisons la même expression régulière pour faire correspondre et supprimer le nom de la catégorie, il est donc efficace de le compiler avec re.compile.

Nous avons une variable category en cours d'exécution qui change chaque fois qu'une nouvelle catégorie est analysée. Toute ligne qui ne définit pas une nouvelle catégorie est ajoutée au dictionnaire categories sous la clé appropriée. Les catégories définies pour la première fois créent une liste sous la bonne clé de dictionnaire, mais les catégories peuvent également être listées plusieurs fois et tout finira sous la bonne clé.

Tous les films répertoriés avant la définition d'une catégorie seront placés dans le dictionnaire sous la clé None.