문제

목록에 저장한 일부 데이터가 있는데 목록을 인쇄하면 다음이 표시됩니다.

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

지금은 각 주기마다 전체 목록을 반복해야 합니다.

각각 500~5,000줄의 파일이 약 60,000개 있기 때문에 처리 시간을 단축하고 싶습니다.

목록에 대한 또 다른 참조를 생성하고 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가 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:])

이것은 비슷한 질문에 대한 이전 답변과 스티븐 후비 대답

다른 팁

당신이 사용할 수있는 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 dataLine in data" 루프 내에 있을 것입니다.

또는 for 루프 대신 반복자를 직접 사용할 수도 있습니다.

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

또한 처리할 파일이 60K개 있다고 언급했습니다.모두 비슷한 형식으로 되어 있나요?다르게 처리해야 합니까?모두 동일한 방식으로 처리할 수 있다면 단일 흐름으로 함께 연결하는 것을 고려할 수 있습니다.

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