Вопрос

У меня есть некоторые данные, которые я сохранил в списке, и если я распечатаю список, я увижу следующее:

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

Прямо сейчас мне приходится перебирать весь список для каждого цикла.

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

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

Это было полезно?

Решение 5

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

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

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

где Tempans - это даталист, теперь я могу написать

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:])

Это основано на более раннем ответе на аналогичный вопрос и Стивен Хьюиг отвечать

Другие советы

Вы можете использовать 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',
 '.',
 '.',
 '.',
 '']

Вы можете прочитать данные в словаре.Предполагая, что вы читаете из файлового объекта 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]

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

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

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

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

Предположительно, это происходит внутри цикла «для строки данных в данных».

В качестве альтернативы вы можете использовать итератор напрямую, а не в цикле for:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top