Question

J'ai quelques données que j'ai stockées dans une liste et si j'imprimer la liste que je vois ce qui suit:

.
.
.
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 qu'il y a d'autres données qui est structuré Similairement mais peuvent ou non pas faire partie de ce septième élément (007). si la première valeur dans le septième point est « 007 A000000 Y » alors je veux créer une liste dictionnaire de certains des éléments de données. Je peux le faire et ont fait en lançant juste à travers tous les éléments dans ma liste et comparer 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 est bien

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 dans chacun entre 500 et 5 000 lignes.

Je l'ai pensé à créer une autre référence à la liste et le comptage des lignes de données jusqu'à dataLine.find ( « » 007 A000000 Y ') == 0. Mais cela ne semble pas comme il est la solution la plus élégante.

Était-ce utile?

La solution 5

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

Je trouve que j'oublie de penser dans les listes et dictionnaires, même si je les utilise. Python a des outils puissants pour travailler avec ces types pour accélérer votre capacité à les manipuler.
J'ai besoin d'une tranche de sorte que les références de tranche sont facilement obtenus 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 appris beaucoup des autres réponses et les apprécie, mais je pense que ce que je avais besoin

D'accord, je vais encore modifier ma réponse. Je l'ai beaucoup appris ici, mais une partie de ce genre de choses est sur ma tête encore et je veux obtenir un code écrit alors que je suis en apprendre davantage 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 réponse

Autres conseils

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() fonctionnerait également si vous voulez vraiment juste de 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',
 '.',
 '.',
 '.',
 '']

Vous pouvez lire les données dans un dictionnaire. En supposant que vous lisez à partir d'un objet-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]

La seule difficulté à utiliser toutes les données dans un dictionnaire est qu'un dictionnaire vraiment grand peut devenir gênant. (Il est ce que nous appelions l'approche "Big Ole Matrix".)

Une solution consiste à construire un index dans le dictionnaire, la création d'une cartographie des key-> offset, selon la méthode de tell pour obtenir la valeur de décalage de fichier. Ensuite, vous pouvez consulter à nouveau la ligne en cherchant avec la méthode seek.

Vous avez dit que vous vouliez faire ceci:

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

On peut supposer que ceci est dans une boucle « pour des lignes de données dans les données ».

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? 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top