Pergunta

Eu tenho alguns dados que eu tenha armazenado em uma lista e se eu imprimir a lista Eu vejo o seguinte:

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

Os pontos antes e depois da seqüência são para representar que não há outros dados que são similarily estruturados, mas pode ou não não fazer parte desse sétimo item (007). se o primeiro valor no sétimo ponto é '007 A000000 Y', em seguida, eu quero criar um dicionário lista de alguns dos itens de dados. Eu posso fazer isso e têm feito isso por apenas correr através de todos os itens em minha lista e comparar seus valores para alguns valores de teste para as variáveis. Por exemplo, uma linha de código como:

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

O que eu quero fazer, porém, é

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

Agora eu estou tendo que percorrer a lista inteira para cada ciclo

Eu quero encurtar o processamento porque eu tenho cerca de 60 mil arquivos que têm entre 500 a 5.000 linhas em cada.

Eu tenho pensado sobre a criação de uma outra referência à lista e contando os datalines até dataLine.find ( '' 007 A000000 Y ') == 0. Mas isso não parece que é a solução mais elegante.

Foi útil?

Solução 5

Ok-enquanto eu estava pesquisando para se certificar de que eu tinha coberto minhas bases me deparei com uma solução:

Eu acho que eu esqueça de pensar em listas e dicionários mesmo que eu usá-los. Python tem algumas ferramentas poderosas para trabalhar com esses tipos de acelerar a sua capacidade de manipulá-los.
Eu preciso de uma fatia de modo que as referências fatia são facilmente obtidos por

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

onde tempans é o datalist agora eu posso escrever

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

Eu acho que eu respondi minha própria pergunta. Eu aprendi muito com as outras respostas e apreciá-los, mas eu acho que isso é o que eu precisava

Ok, eu estou indo para mais editar a minha resposta. Eu tenho aprendido muito aqui, mas algumas dessas coisas é sobre a minha cabeça ainda e quero obter algum código escrito enquanto eu estou aprendendo mais sobre esta ferramenta fantástica.

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

Este é baseado em uma resposta anterior a uma pergunta semelhante e resposta de Steven Huwig

Outras dicas

Você pode usar itertools.groupby() para segmentar sua seqüência em vários sub-sequências.

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() também funcionaria se você realmente só quer buscar-se a essa linha,

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

Você pode ler os dados em um dicionário. Supondo que você está lendo de um arquivo-como objeto infile:

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

Agora, se você quiser ler a linha após '007 A000000 Y', você pode fazê-lo como:

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

A única dificuldade com o uso de todos os dados em um dicionário é que de facto um grande dicionário pode tornar-se problemático. (É o que nós costumávamos chamar a abordagem "Big Ole Matrix").

A solução para isso é para construir um index no dicionário, criando um mapeamento de chave-> offset, utilizando o método tell para obter o valor de deslocamento de arquivo. Em seguida, você pode consultar a linha novamente, buscando com o método seek.

Você disse que queria fazer isso:

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

Presumivelmente, isso é dentro de um loop "para DATALINE em dados".

Como alternativa, você poderia usar um iterador diretamente em vez de em um loop:

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

Você também mencionar ter 60K arquivos para processo. todos eles são formatados da mesma forma? Será que eles precisam ser processadas de forma diferente? Se todos eles podem ser processados ??da mesma forma, você poderia considerar encadeando-os em um único fluxo:

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

Isso permite que você preguiçosamente processar todos os seus arquivos em um único iterador. Não tenho certeza se isso ajuda a sua situação atual, mas eu pensei que vale a pena mencionar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top