2014-07-19 6 views
1

저는 Windows 7에서 python-3.x로 작업하고 있습니다. 수백만 개의 문자로 구성된 문자열이 있습니다. 예를 들어 :문자열의 특정 문자 범위 찾기

ATCGNNNATCGATNNNNNATCGANTCG 

N 범위를 얻고 싶습니다. 여기에 [[4,7], [13,18], [23,24]]. 큰 데이터이고이 방법이 너무 느리기 때문에 나는 단지 N의 위치를 ​​취한 다음 범위로 변환 할 수 없습니다. 정말 쉬운 문제인 것처럼 보이지만 사실 내 마음에는 좋은 길은 없습니다. 빠른 방법이 있나요?

답변

10

이 문자 수백만의 문자열로 확장,하지만 당신은 regular expressions을 시도 할 수있는 방법을 확실하지 :

>>> import re 
>>> data = "ATCGNNNATCGATNNNNNATCGANTCG" 
>>> spans = (g.span() for g in re.finditer('N+', data)) 
>>> list(spans) 
[(4, 7), (13, 18), (23, 24)] 

업데이트 :는, A, C, G, T의 임의로 생성 된 문자열이 시도하고 N. 1,000,000 문자의 경우 list(spans)은 1 초 미만이고 10,000,000은 새로운 컴퓨터에서는 약 10 초 걸려 약 1,600,000 개의 N 그룹을 찾습니다.

+3

'g.span()'을 사용하면 속도가 약간 빨라질 수 있습니다. – DSM

+1

수백만 자의 경우 반복자를 한 번에 소비하지는 않겠지 만 위대한 접근 방식 +1 –

+0

또한'g.span() '주위에 공백을 넣을 필요가 없음 –

2

다시없는 솔루션 :

from itertools import chain 

def find_ranges(it, elem): 
    start = None 
    for i, e in enumerate(chain(it, [None])): 
     if not start and e == elem: 
      start = i 
     elif start and e != elem: 
      yield (start, i) 
      start = None 

ipython의 마법 %의 timeit로 측정 :

In [1]: import random 
In [2]: s = [random.choice("ACGTN") for i in range(1000000)] 
In [3]: %timeit list(find_ranges(s, "N")) 
10 loops, best of 3: 164 ms per loop 

편집 :이 때 작동하도록하기 위해, 체인 끝에 가드를 추가 시퀀스의 마지막 항목은 검색된 요소입니다.

+0

+1. 비교를 위해서 : 두 시스템을 내 시스템에서 테스트했고, 정규식 접근 방식은 여전히 ​​두 배 빠릅니다. 내 컴퓨터가 정말로 더 빠르지는 않을 것 같습니다 ... –

+0

고마워요. 어쩌면 regex 기반 솔루션이 더 빠릅니다. 왜냐하면 광 모듈이 순수한 파이썬 인 동안 re 모듈이 C로 구현되기 때문입니다. 나는 C에서 구현 된 동일한 알고리즘을 정규식으로 계산할 수 있다고 믿는다. :) –