Domanda

Ho alcuni dati che ho memorizzate in un elenco e se stampare l'elenco vedo il seguente:

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

I punti prima e dopo la sequenza sono a rappresentare che non v'è altro dati che vengono similmente strutturata ma potrebbe o non potrebbe non essere parte di questo settimo punto (007). se il primo valore nel settimo punto è '007 A000000 Y' allora voglio creare un elenco dizionario di alcuni degli elementi di dati. Posso fare questo e lo hanno fatto semplicemente che attraversa tutti gli elementi nella mia lista e confrontando i loro valori ad alcuni valori di test per le variabili. Per esempio una riga di codice come:

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

Quello che voglio fare, però, è

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

In questo momento mi sto avendo per scorrere l'intero elenco per ogni ciclo

Voglio accorciare il trattamento perché ho circa 60K file che hanno tra i 500 ei 5.000 linee in ciascuno.

ho pensato di creare un altro riferimento alla lista e contando le linee dati fino dataLine.find ( '' 007 A000000 Y ') == 0. Ma questo non sembra come se fosse la soluzione più elegante.

È stato utile?

Soluzione 5

Ok-mentre ero Googling per assicurarsi che aveva coperto le mie basi mi sono imbattuto in una soluzione:

Trovo che ho dimenticato di pensare in liste e dizionari, anche se li uso. Python ha alcuni potenti strumenti per lavorare con questi tipi di accelerare la vostra capacità di manipolare loro.
Ho bisogno di una fetta così i riferimenti delle sezioni sono facilmente ottenuti da

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

dove tempans è il datalist ora posso scrivere

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

Credo di aver risposto alla mia domanda. Ho imparato molto dalle altre risposte e li apprezzo, ma penso che questo è ciò che mi serviva

Va bene ho intenzione di modificare ulteriormente la mia risposta. Ho imparato molto qui, ma alcune di queste cose è sopra la mia testa ancora e voglio ottenere qualche codice scritto, mentre io sto imparando di più su questo fantastico strumento.

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

Questo è basato su una precedente risposta a una domanda simile e risposta di Steven Huwig

Altri suggerimenti

È possibile utilizzare itertools.groupby() per segmentare la sequenza in più sotto-sequenze.

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() potrebbe anche funzionare se si vuole veramente solo a cercare fino a quella linea,

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',
 '.',
 '.',
 '.',
 '']

Si potrebbe leggere i dati in un dizionario. Supponendo che si sta leggendo da un oggetto infile simile a file:

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

Ora, se volete leggere la linea dopo '007 A000000 Y', si può fare in modo:

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

L'unica difficoltà con l'utilizzo di tutti i dati in un dizionario è che davvero un grande dizionario può diventare fastidioso. (E 'quello che abbiamo usato per chiamare l'approccio "Big Ole Matrix".)

Una soluzione a questo è di costruire un index nel Dizionario, la creazione di una mappatura di chiave-> offset, utilizzando il metodo tell per ottenere il valore di offset file. Poi si può fare riferimento alla linea di nuovo cercando con il metodo seek.

Hai detto che volevi fare questo:

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

Probabilmente questo è all'interno di un "per Dataline nei dati" loop.

In alternativa, è possibile utilizzare un iteratore direttamente invece che in un ciclo for:

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

È anche parlare di dover 60K file da elaborare. Sono tutte formattati in modo simile? Hanno bisogno di essere trattati in modo diverso? Se tutti possono essere trattati allo stesso modo, si potrebbe prendere in considerazione loro concatenamento insieme in un unico flusso:

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

Questo consente di elaborare pigramente tutti i file in un singolo iteratore. Non sono sicuro se questo aiuta la vostra situazione attuale, ma ho pensato che vale la pena menzionare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top