2009-04-16 10 views
1

J'ai quelques données que j'ai stockées dans une liste et si j'imprimer la liste je vois ce qui suit:flux de contrôle du programme en Python

. 
. 
. 
007 A000000 Y 
007 B000000 5 
007 C010100 1 
007 C020100 ACORN FUND 
007 C030100 N 
007 C010200 2 
007 C020200 ACORN INTERNATIONAL 
007 C030200 N 
007 C010300 3 
007 C020300 ACORN USA 
007 C030300 N 
007 C010400 4 
. 
. 
. 

Les points avant et après la séquence doivent représenter cette il existe d'autres données qui sont structurées de manière similaire mais pourraient ou non faire partie de ce septième élément (007). Si la première valeur du septième élément est '007 A000000 Y', je souhaite créer une liste de certains des éléments de données. Je peux le faire et je l'ai fait en parcourant simplement tous les éléments de ma liste et en comparant leurs valeurs à des valeurs de test pour les variables. Par exemple, une ligne de code comme:

if dataLine.find('007 B')==0: 
    numberOfSeries=int(dataLine.split()[2]) 

Ce que je veux faire bien est

if dataLine.find(''007 A000000 Y')==0: 
    READ THE NEXT LINE RIGHT HERE 

En ce moment je suis d'avoir à parcourir toute la liste pour chaque cycle

Je veux raccourcir le traitement parce que j'ai environ 60K fichiers qui ont entre 500 à 5 000 lignes dans chacun.

J'ai pensé à créer une autre référence à la liste et à compter les données jusqu'à dataLine.find ('' 007 A000000 Y ') == 0. Mais cela ne semble pas être la solution la plus élégante.

+0

Divisez cette dernière partie en une réponse! C'est une bonne question et d'autres personnes pourraient trouver ce que vous avez trouvé utile :) –

Répondre

0

Ok-alors que je recherche sur Google pour vous assurer que j'avais couvert mes bases je suis tombé une solution:

Je trouve que j'oublie de penser dans les listes et les dictionnaires même si je les utilise. Python a quelques outils puissants pour travailler avec ces types afin d'accélérer votre capacité à les manipuler.
je besoin d'une tranche de sorte que les références de tranche sont facilement obtenues par

beginPosit = tempans.index('007 A000000 Y') 
endPosit = min([i for i, item in enumerate(tempans) if '008 ' in item]) 

où tempans est le datalist maintenant je peux écrire

for line in tempans[beginPosit:endPosit]: 
    process each line 

Je crois avoir répondu à ma propre question. J'ai beaucoup appris des autres réponses et je les apprécie mais je pense que c'est ce dont j'avais besoin

Okay Je vais modifier davantage ma réponse. J'ai beaucoup appris ici, mais certaines de ces choses sont encore sur ma tête et je veux obtenir du code pendant que j'en apprends plus sur cet outil fantastique.

from itertools import takewhile 
beginPosit = tempans.index('007 A000000 Y') 
new=takewhile(lambda x: '007 ' in x, tempans[beginPosit:]) 

Ceci est basé sur une version antérieure réponse à une question similaire et Steven Huwig's réponse

+0

Ouais, mais maintenant vous lisez deux fois la liste entière juste pour trouver vos indices de tranche – kurosch

2

Vous pouvez lire les données dans un dictionnaire. En supposant que vous lisez à partir d'un objet de type fichier infile:

from collections import defaultdict 
data = defaultdict(list) 
for line in infile: 
    elements = line.strip().split() 
    data[elements[0]].append(tuple(elements[1:])) 

Maintenant, si vous voulez lire la ligne après 007 A000000 Y ', vous pouvez le faire comme:

# find the index of ('A000000', 'Y') 
idx = data['007'].index(('A000000', 'Y')) 
# get the next line 
print data['007'][idx+1] 
2

La seule difficulté avec l'utilisation de toutes les données dans un dictionnaire est qu'un très gros dictionnaire peut devenir gênant. (Il est ce que nous appelions l'approche « Big Ole Matrix ».)

Une solution est de construire un indice dans le dictionnaire, la création d'une cartographie de key-> offset, en utilisant la méthode tell pour obtenir la valeur de décalage de fichier. Ensuite, vous pouvez vous référer à la ligne à nouveau en cherchant avec la méthode seek.

3

Vous pouvez utiliser itertools.groupby() pour segmenter votre séquence en plusieurs sous-séquences.

import itertools 

for key, subseq in itertools.groupby(tempans, lambda s: s.partition(' ')[0]): 
    if key == '007': 
    for dataLine in subseq: 
     if dataLine.startswith('007 B'): 
     numberOfSeries = int(dataLine.split()[2]) 

itertools.dropwhile() fonctionne également si vous voulez vraiment juste chercher à cette ligne,

list(itertools.dropwhile(lambda s: s != '007 A000000 Y', tempans)) 
['007 A000000 Y', 
'007 B000000 5', 
'007 C010100 1', 
'007 C020100 ACORN FUND', 
'007 C030100 N', 
'007 C010200 2', 
'007 C020200 ACORN INTERNATIONAL', 
'007 C030200 N', 
'007 C010300 3', 
'007 C020300 ACORN USA', 
'007 C030300 N', 
'007 C010400 4', 
'.', 
'.', 
'.', 
''] 
0

Vous avez dit que vous vouliez faire ceci:

if dataLine.find(''007 A000000 Y')==0: 
    READ THE NEXT LINE RIGHT HERE 

ceci est sans doute dans un « pour DATALINE des données " boucle.

Sinon, vous pouvez utiliser un itérateur directement au lieu d'une boucle:

>>> i = iter(data) 
>>> while i.next() != '007 A000000 Y': pass # find your starting line 
>>> i.next() # read the next line 
'007 B000000 5' 

Vous mentionnez également avoir 60K fichiers à traiter. Sont-ils tous formatés de la même manière? Doivent-ils être traités différemment? S'ils peuvent tous être traités de la même façon, vous pouvez envisager de les enchaînant dans un seul flux:

def gfind(directory, pattern="*"): 
    for name in fnmatch.filter(os.listdir(directory), pattern): 
     yield os.path.join(directory, name) 

def gopen(names): 
    for name in names: 
     yield open(name, 'rb') 

def gcat(files): 
    for file in files: 
     for line in file: 
      yield line 

data = gcat(gopen(gfind('C:\datafiles', '*.dat'))) 

Cela vous permet de traiter paresseusement tous vos fichiers dans un seul itérateur. Je ne sais pas si cela aide votre situation actuelle, mais je pense qu'il vaut la peine de mentionner.

Questions connexes