2009-04-16 2 views
1

У меня есть некоторые данные, которые я сохраненные в списке, и если я распечатать список я вижу следующее:Программа управление потоком в 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 
. 
. 
. 

Точек до и после последовательности должны представлять, что есть другие данные, которые аналогично структурированы, но могут или не могут быть частью этого седьмого пункта (007). если первое значение в седьмом элементе - «007 A000000 Y», тогда я хочу создать список слов из некоторых элементов данных. Я могу сделать это и сделал это, просто выполнив все элементы в моем списке и сравнив их значения с некоторыми тестовыми значениями для переменных. Например строка кода, как:

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

То, что я хочу сделать, хотя это

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

Сейчас я с перебрать весь список для каждого цикла

Я хочу сократите обработку, потому что у меня около 60K файлов, которые имеют от 500 до 5000 строк в каждом.

Я подумал о создании другой ссылки на список и подсчета данных до тех пор, пока dataLine.find ('' 007 A000000 Y ') == 0. Но это не похоже, что это самое элегантное решение.

+0

Разделите эту последнюю часть на ответ! Это хороший вопрос, и другие люди могут найти то, что вам пригодилось :) –

ответ

0

Хорошо, в то время как я был погуглить, чтобы убедиться, что я закрыла свои базы я наткнулся решение:

Я нахожу, что забываю думать в списках и словарях, хотя я их использую. У Python есть несколько мощных инструментов для работы с этими типами, чтобы ускорить их манипулирование ими.
мне нужен кусок так ссылка среза легко получается

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

где tempans является DataList теперь я могу написать

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

Я думаю, что я ответил на мой собственный вопрос. Я многому научился из других ответов и ценю их, но я думаю, что это то, что мне нужно

Хорошо, я продолжу редактирование своего ответа. Я многому научился здесь, но некоторые из этих вещей все еще над моей головой, и я хочу получить код, написанный, пока я больше узнаю об этом фантастическом инструменте.

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

Это основано на ранее ответ на подобный вопрос и Steven Huwig's ответ

+0

Да, но теперь вы просматриваете весь список дважды, чтобы найти свои индексы среза – kurosch

2

Вы можете прочитать данные в словаре. Предполагая, что вы читаете из файла типа объекта infile:

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

Теперь, если вы хотите, чтобы прочитать строку после «007 A000000 Y», вы можете сделать это следующим образом:

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

Единственная трудность с использованием всех данных в словаре заключается в том, что действительно большой словарь может стать хлопотным. (Это то, что мы привыкли называть «Big Ole Матрицей» подход.)

Решением этой проблемы состоит в построении индекса в Словаре, создавая отображение кнопочной> смещения, используя метод tell, чтобы получить значение смещения файла. Затем вы можете обратиться к строке снова, ища метод seek.

3

Вы можете использовать itertools.groupby(), чтобы сегментировать свою последовательность на несколько подпоследовательностей.

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() также будет работать, если вы на самом деле просто хотят, чтобы искать до этой линии,

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

Вы сказали, что вы хотели бы сделать это:

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

Предположительно, это в пределах «для DATALINE в данных "петля.

В качестве альтернативы, можно использовать итератор непосредственно вместо того, чтобы в цикле:

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

Вы также упомянуть, имея 60 тысяч файлов для обработки. Все они отформатированы аналогично? Нужно ли их обрабатывать по-разному? Если все они могут быть обработаны таким же образом, вы могли бы рассмотреть возможность сцепления их вместе в одном потоке:

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

Это позволяет обрабатывать лениво все файлы в одном итератора. Не уверен, что это поможет вашей текущей ситуации, но я думал, что стоит упомянуть.

 Смежные вопросы

  • Нет связанных вопросов^_^