Pregunta

Tengo algunos datos que he almacenado en una lista y si imprimo la lista veo lo siguiente:

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

Los puntos antes y después de la secuencia representan que hay otros datos que están estructurados de manera similar pero que podrían o no ser parte de este séptimo elemento (007).Si el primer valor del séptimo elemento es '007 A000000 Y', entonces quiero crear una lista de diccionario de algunos de los elementos de datos.Puedo hacer esto y lo he hecho simplemente revisando todos los elementos de mi lista y comparando sus valores con algunos valores de prueba para las variables.Por ejemplo, una línea de código como:

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

Lo que quiero hacer es

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

En este momento tengo que recorrer la lista completa para cada ciclo.

Quiero acortar el procesamiento porque tengo alrededor de 60 000 archivos que tienen entre 500 y 5000 líneas cada uno.

He pensado en crear otra referencia a la lista y contar las líneas de datos hasta dataLine.find(''007 A000000 Y')==0.Pero esa no parece ser la solución más elegante.

¿Fue útil?

Solución 5

Está bien, mientras yo estaba buscando en Google para asegurarse de que había cubierto mis bases que me encontré una solución:

Me parece que me olvide de pensar en listas y diccionarios a pesar de que los uso. Python tiene algunas herramientas poderosas para trabajar con estos tipos de acelerar su capacidad para manipularlos.
Necesito una rebanada por lo que las referencias rebanada se obtienen fácilmente mediante

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

donde tempans es la lista de datos Ahora puedo escribir

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

Creo que respondí a mi propia pregunta. He aprendido mucho de las otras respuestas y los aprecio pero creo que esto es lo que necesitaba

Está bien voy a seguir editando mi respuesta. He aprendido mucho aquí, pero algunas de estas cosas es por encima de mi cabeza todavía y quiero conseguir algo de código escrito mientras estoy aprendiendo más sobre esta fantástica herramienta.

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

Esto se basa en una respuesta anterior a una pregunta similar y respuesta de Steven Huwig

Otros consejos

Puede utilizar itertools.groupby() para segmentar su secuencia en múltiples sub-secuencias.

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() también funcionaría si realmente sólo quiere buscar hasta esa línea,

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

Usted puede leer los datos en un diccionario. Suponiendo que está leyendo desde un infile objeto de fichero:

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

Ahora bien, si desea leer la línea después de '007 A000000 Y', puede hacerlo como:

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

La única dificultad con el uso de todos los datos en un diccionario es que un diccionario muy grande puede llegar a ser problemático. (Es lo que solíamos llamar el enfoque "Big Ole Matrix".)

Una solución a esto es construir un index en el diccionario, la creación de un mapeo de número-> offset, utilizando el método de tell para obtener el valor de desplazamiento de archivos. A continuación, se puede hacer referencia a la línea de nuevo mediante la búsqueda con el método seek.

Dijiste que querías hacer esto:

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

Presumiblemente, esto está dentro de un bucle "para línea de datos en datos".

Alternativamente, puedes usar un iterador directamente en lugar de en un bucle for:

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

También mencionas que tienes archivos de 60K para procesar.¿Están todos formateados de manera similar?¿Es necesario procesarlos de manera diferente?Si todos se pueden procesar de la misma manera, podría considerar encadenarlos en un solo flujo:

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

Esto le permite procesar perezosamente todos sus archivos en un solo iterador.No estoy seguro de si eso ayuda a tu situación actual, pero pensé que valía la pena mencionarlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top