2017-05-04 7 views
3

문자열에서 부분 문자열 목록의 위치를 ​​어떻게 찾을 수 있습니까? 문자열을 감안할 때문자열에서 부분 문자열 목록의 위치를 ​​찾는 방법은 무엇입니까?

:

". 세인트 피터 스 버그 행 비행기는, 이집트의 시나이 사막에 추락 단지 23 분 이륙 토요일 샤름 엘 - 셰이크에서"

그리고 문자열의 목록 :

[ '을', '비행기', ',', '대한', '바운드', '세인트', '피터', ',' '이집트', '시', '시나이', '사막', '그냥', '23', '분', '이후', '이륙', '에서' .에 ','샴 ','엘 - 셰이크 ',' ','토요일 ',' ']

원하는 출력 :

>>> s = "The plane, bound for St Petersburg, crashed in Egypt's Sinai desert just 23 minutes after take-off from Sharm el-Sheikh on Saturday." 
>>> tokens = ['The', 'plane', ',', 'bound', 'for', 'St', 'Petersburg', ',', 'crashed', 'in', 'Egypt', "'s", 'Sinai', 'desert', 'just', '23', 'minutes', 'after', 'take-off', 'from', 'Sharm', 'el-Sheikh', 'on', 'Saturday', '.'] 
>>> find_offsets(tokens, s) 
[(0, 3), (4, 9), (9, 10), (11, 16), (17, 20), (21, 23), (24, 34), 
     (34, 35), (36, 43), (44, 46), (47, 52), (52, 54), (55, 60), (61, 67), 
     (68, 72), (73, 75), (76, 83), (84, 89), (90, 98), (99, 103), (104, 109), 
     (110, 119), (120, 122), (123, 131), (131, 132)] 

출력에 대한 설명, 첫 번째 하위 문자열 "The"는 s 문자열을 사용하여 (start, end) 색인을 사용하여 찾을 수 있습니다. 그래서 원하는 출력에서.

그래서 우리는 우리가 문자열의 목록을 다시 얻을 수 있습니다 원하는 출력, 즉의 정수의 모든 튜플을 통해 루프

>>> [s[start:end] for start, end in out] 
['The', 'plane', ',', 'bound', 'for', 'St', 'Petersburg', ',', 'crashed', 'in', 'Egypt', "'s", 'Sinai', 'desert', 'just', '23', 'minutes', 'after', 'take-off', 'from', 'Sharm', 'el-Sheikh', 'on', 'Saturday', '.'] 

내가하려고 한 경우 :

def find_offset(tokens, s): 
    index = 0 
    offsets = [] 
    for token in tokens: 
     start = s[index:].index(token) + index 
     index = start + len(token) 
     offsets.append((start, index)) 
    return offsets 

이 있습니까 문자열에서 하위 문자열 목록의 위치를 ​​찾는 또 다른 방법은 무엇입니까?

답변

1

에 외에는 방법이 없다 각각에 대해 전체 텍스트를 새로 스캔하십시오.

데이터에서 보았 듯이 텍스트의 순서대로 주어진 텍스트의 부분 인 경우 각각 나머지 개를 검색하기가 쉽습니다. 하지만 매번 텍스트를자를 필요는 없습니다.

def spans(text, fragments): 
    result = [] 
    point = 0 # Where we're in the text. 
    for fragment in fragments: 
     found_start = text.index(fragment, point) 
     found_end = found_start + len(fragment) 
     result.append((found_start, found_end)) 
     point = found_end 
    return result 

테스트 :

>>> spans('foo in bar', ['foo', 'in', 'bar']) 
[(0, 3), (4, 6), (7, 10)] 

이 모든 조각이 올바른 위치에있는 텍스트에 존재하는 것으로 가정합니다. 출력 형식에는 불일치보고의 예가 나와 있지 않습니다. .index 대신 .find을 사용하면 부분적으로 만 도움이 될 수 있습니다.

4

첫 번째 솔루션 : 첫 번째 솔루션의 문제를 해결하기 위해

#use list comprehension and list.index function. 
[tuple((s.index(e),s.index(e)+len(e))) for e in t] 

두 번째 해결책은 : 우리는 문자열 나지 않을 경우

def find_offsets(tokens, s): 
    tid = [list(e) for e in tokens] 
    i = 0 
    for id_token,token in enumerate(tid): 
     while (token[0]!=s[i]):    
      i+=1 
     tid[id_token] = tuple((i,i+len(token))) 
     i+=len(token) 

    return tid 


find_offsets(tokens, s) 
Out[201]: 
[(0, 3), 
(4, 9), 
(9, 10), 
(11, 16), 
(17, 20), 
(21, 23), 
(24, 34), 
(34, 35), 
(36, 43), 
(44, 46), 
(47, 52), 
(52, 54), 
(55, 60), 
(61, 67), 
(68, 72), 
(73, 75), 
(76, 83), 
(84, 89), 
(90, 98), 
(99, 103), 
(104, 109), 
(110, 119), 
(120, 122), 
(123, 131), 
(131, 132)] 

#another test 
s = 'The plane, plane' 
t = ['The', 'plane', ',', 'plane'] 
find_offsets(t,s) 
Out[212]: [(0, 3), (4, 9), (9, 10), (11, 16)] 
+1

멋지게 짧은뿐만 아니라 쾌적하게 비효율적 호출'있는 .index()'를 두 번 누릅니다. – 9000

+0

또한 반복되는 단어가 있으면 작동하지 않습니다. '.index()'는 항상 첫 번째 인스턴스 만 가져 오게됩니다 = ( – alvas

+0

''평면, 평면 ''; '=' '평면', '' ''평면 ']' – alvas

1
import re 

s = "The plane, bound for St Petersburg, crashed in Egypt's Sinai desert just 23 minutes after take-off from Sharm el-Sheikh on Saturday." 
tokens = ['The', 'plane', ',', 'bound', 'for', 'St', 'Petersburg', ',', 'crashed', 'in', 'Egypt', "'s", 'Sinai', 'desert', 'just', '23', 'minutes', 'after', 'take-off', 'from', 'Sharm', 'el-Sheikh', 'on', 'Saturday', '.'] 


for token in tokens: 
    pattern = re.compile(re.escape(token)) 
    print(pattern.search(s).span()) 

결과

(0, 3) 
(4, 9) 
(9, 10) 
(11, 16) 
(17, 20) 
(21, 23) 
(24, 34) 
(9, 10) 
(36, 43) 
(44, 46) 
(47, 52) 
(52, 54) 
(55, 60) 
(61, 67) 
(68, 72) 
(73, 75) 
(76, 83) 
(84, 89) 
(90, 98) 
(99, 103) 
(104, 109) 
(110, 119) 
(120, 122) 
(123, 131) 
(131, 132)