2013-09-07 2 views
1

고정 너비 파일에는 수십만 개의 가치가 있습니다. 문자열 old_values를 찾고 new_values의 해당 위치에있는 문자열로 바꾸고 싶습니다. 나는 한 번에 하나씩 반복 할 수 있지만, 내가 알기에 충분히 전문적이지 않은 훨씬 빠른 방법이 있다는 것을 거의 확신한다.python3에 여러 대체 값이 있습니다.

old_values = ('0000}', '0000J', '0000K', '0000L', '0000M', '0000N') # and many more 
new_values = (' -0', ' -1', ' -2', ' -3', ' -4', ' -5') # and many more 
file_snippet = '00000000000000010000}0000000000000000000200002000000000000000000030000J0000100000000000000500000000000000000000000' # each line is >7K chars long and there are over 6 gigs of text data 

각 값을 반복하고 각 행에서 .replace를 실행하는 것이 느려 보입니다. 예 :

for x in len(old_values): 
    line.replace(old_values[x], new_values[x]) 

속도 향상을위한 도움말은 무엇입니까?

+1

현재 속도가 느린 방법을 게시하십시오. –

+0

'더 많은'이 몇 개나됩니까? 그들은 모두 같은 길이입니까? 그들은 모두 같은 길이로 오프셋되어 있습니까? –

+0

변경하려는 경우 결국 데이터를 반복해야합니다. –

답변

3

데이터를 문자 단위로 처리하고 매핑을 찾으면 대체하는 코드입니다. 이것은 교체해야 할 각 데이터가 절대적으로 고유하다고 가정합니다. 귀하의 예제 데이터에

def replacer(instring, mapping): 

    item = '' 

    for char in instring: 
     item += char 
     yield item[:-5] 
     item = item[-5:] 
     if item in mapping: 
      yield mapping[item] 
      item = '' 

    yield item 


old_values = ('0000}', '0000J', '0000K', '0000L', '0000M', '0000N') 
new_values = (' -0', ' -1', ' -2', ' -3', ' -4', ' -5') 
value_map = dict(zip(old_values, new_values)) 

file_snippet = '00000000000000010000}0000000000000000000200002000000000000000000030000J0000100000000000000500000000000000000000000' # each line is >7K chars long and there are over 6 gigs of text data 

result = ''.join(replacer(file_snippet, value_map)) 
print result 

이 제공 :

old_values = ('0000}', '0000J', '0000K', '0000L', '0000M', '0000N') 
new_values = (' -0', ' -1', ' -2', ' -3', ' -4', ' -5') 
value_map = dict(zip(old_values, new_values)) 

file_snippet = '00000000000000010000}0000000000000000000200002000000000000000000030000J0000100000000000000500000000000000000000000' # each line is >7K chars long and there are over 6 gigs of text data 

result = [] 
for chunk in [ file_snippet[i:i+5] for i in range(0, len(file_snippet), 5) ]: 
    if chunk in value_map: 
     result.append(value_map[chunk]) 
    else: 
     result.append(chunk) 

result = ''.join(result) 
print result 

:

0000000000000001 -0000000000000000000020000200000000000000000003 -10000100000000000000500000000000000000000000 

더 빠른 방법은 데이터가 그런 식으로 맞는 경우, 5 문자 조각으로 데이터를 분할하는 것 선행 0을 제거하지 않으면 결과 데이터가 대체되지 않습니다.

000000000000001 -0000000000000000000020000200000000000000000003 -10000100000000000000500000000000000000000000 

위와 동일합니다.

+0

아주 좋은. 많이 thry vry! – Don

2

대체 매핑 (dict)를 만드는 것들을 빠르게합니다 :

import timeit 

input_string = '00000000000000010000}0000000000000000000200002000000000000000000030000J0000100000000000000500000000000000000000000' 
old_values = ('0000}', '0000J', '0000K', '0000L', '0000M', '0000N') 
new_values = (' -0', ' -1', ' -2', ' -3', ' -4', ' -5') 
mapping = dict(zip(old_values,new_values)) 


def test_replace_tuples(input_string, old_values, new_values): 
    for x in xrange(len(old_values)): 
     input_string = input_string.replace(old_values[x], new_values[x]) 
    return input_string 


def test_replace_mapping(input_string, mapping): 
    for k, v in mapping.iteritems(): 
     input_string = input_string.replace(k, v) 
    return input_string 


print timeit.Timer('test_replace_tuples(input_string, old_values, new_values)', 
        'from __main__ import test_replace_tuples, input_string, old_values, new_values').timeit(10000) 

print timeit.Timer('test_replace_mapping(input_string, mapping)', 
        'from __main__ import test_replace_mapping, input_string, mapping').timeit(10000) 

인쇄 :

0.0547060966492 
0.048122882843 

참고, 결과가 다른 입력 다를 수 실제 데이터를 테스트 할 수있다.

+0

이 작은 차이는 훨씬 큰 문자열이있는 실제 데이터로 사라질 가능성이 큽니다. 당신이보고있는 것은 튜플에서의 검색이 약간의 시간이 걸릴 가능성이 높습니다. 긴 문자열을 사용하면 실제로 차이가 사라집니다. –

+0

@LennartRegebro 알고 잘 부탁드립니다. 감사합니다. 실제로 OP에 적용 할 수 있다면'pypy '제안에 대해 실제로 생각하고있었습니다. – alecxe

+0

Pypy가 실제로 도움이 될지 모르지만 올바른 알고리즘을 선택하면 더 많은 도움이 될 것입니다. :-) –