IT박스

파이썬에서 문자열 내에서 여러 문자열 찾기

itboxs 2020. 11. 23. 07:56
반응형

파이썬에서 문자열 내에서 여러 문자열 찾기


파이썬에서 문자열 내에서 여러 문자열을 찾으려면 어떻게해야합니까? 이걸 고려하세요:

>>> text = "Allowed Hello Hollow"
>>> text.find("ll")
1
>>> 

따라서의 첫 번째 발생은 ll예상대로 1입니다. 다음 발생을 어떻게 찾습니까?

동일한 질문이 목록에 유효합니다. 중히 여기다:

>>> x = ['ll', 'ok', 'll']

ll인덱스로 모든를 어떻게 습니까?


정규식을 사용 re.finditer하여 겹치지 않는 모든 항목을 찾을 수 있습니다 .

>>> import re
>>> text = 'Allowed Hello Hollow'
>>> for m in re.finditer('ll', text):
         print('ll found', m.start(), m.end())

ll found 1 3
ll found 10 12
ll found 16 18

또는 정규식의 오버 헤드를 원하지 않는 경우 다음 인덱스 str.find를 가져 오기 위해 반복적으로 사용할 수도 있습니다 .

>>> text = 'Allowed Hello Hollow'
>>> index = 0
>>> while index < len(text):
        index = text.find('ll', index)
        if index == -1:
            break
        print('ll found at', index)
        index += 2 # +2 because len('ll') == 2

ll found at  1
ll found at  10
ll found at  16

이것은 목록 및 기타 시퀀스에도 적용됩니다.


당신이 찾고있는 것은 string.count

"Allowed Hello Hollow".count('ll')
>>> 3

이것이 도움이되기를 바랍니다.
참고 : 이것은 겹치지 않는 발생만을 캡처합니다.


목록 예의 경우 이해력을 사용하십시오.

>>> l = ['ll', 'xx', 'll']
>>> print [n for (n, e) in enumerate(l) if e == 'll']
[0, 2]

문자열의 경우 :

>>> text = "Allowed Hello Hollow"
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 10, 16]

이것은 "ll"의 인접 실행을 나열합니다.

>>> text = 'Alllowed Hello Holllow'
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 2, 11, 17, 18]

FWIW, 여기에 poke의 솔루션 보다 깔끔하다고 생각하는 비 RE 대안이 몇 가지 있습니다 .

첫 번째 사용 str.index및 확인 ValueError:

def findall(sub, string):
    """
    >>> text = "Allowed Hello Hollow"
    >>> tuple(findall('ll', text))
    (1, 10, 16)
    """
    index = 0 - len(sub)
    try:
        while True:
            index = string.index(sub, index + len(sub))
            yield index
    except ValueError:
        pass

두 번째 테스트는 다음 을 사용하여 str.find의 센티널을 사용 하고 확인합니다 .-1iter

def findall_iter(sub, string):
    """
    >>> text = "Allowed Hello Hollow"
    >>> tuple(findall_iter('ll', text))
    (1, 10, 16)
    """
    def next_index(length):
        index = 0 - length
        while True:
            index = string.find(sub, index + length)
            yield index
    return iter(next_index(len(sub)).next, -1)

이러한 함수를 목록, 튜플 또는 기타 반복 가능한 문자열에 적용하려면 다음과 같이 함수를 인수 중 하나로 취하는 상위 수준 함수를 사용할 수 있습니다 .

def findall_each(findall, sub, strings):
    """
    >>> texts = ("fail", "dolly the llama", "Hello", "Hollow", "not ok")
    >>> list(findall_each(findall, 'll', texts))
    [(), (2, 10), (2,), (2,), ()]
    >>> texts = ("parallellized", "illegally", "dillydallying", "hillbillies")
    >>> list(findall_each(findall_iter, 'll', texts))
    [(4, 7), (1, 6), (2, 7), (2, 6)]
    """
    return (tuple(findall(sub, string)) for string in strings)

목록 예 :

In [1]: x = ['ll','ok','ll']

In [2]: for idx, value in enumerate(x):
   ...:     if value == 'll':
   ...:         print idx, value       
0 ll
2 ll

'll'이 포함 된 목록의 모든 항목을 원하면 그렇게 할 수도 있습니다.

In [3]: x = ['Allowed','Hello','World','Hollow']

In [4]: for idx, value in enumerate(x):
   ...:     if 'll' in value:
   ...:         print idx, value
   ...:         
   ...:         
0 Allowed
1 Hello
3 Hollow

>>> for n,c in enumerate(text):
...   try:
...     if c+text[n+1] == "ll": print n
...   except: pass
...
1
10
16

일반적으로 프로그래밍을 처음 접하고 온라인 자습서를 통해 작업합니다. 이 작업도 요청 받았지만 지금까지 배운 방법 (기본적으로 문자열과 루프) 만 사용했습니다. 이것이 여기에 가치를 추가하는지 확실하지 않으며 이것이 당신이하는 방법이 아니라는 것을 알고 있지만 이것과 함께 작동합니다.

needle = input()
haystack = input()
counter = 0
n=-1
for i in range (n+1,len(haystack)+1):
   for j in range(n+1,len(haystack)+1):
      n=-1
      if needle != haystack[i:j]:
         n = n+1
         continue
      if needle == haystack[i:j]:
         counter = counter + 1
print (counter)

이 버전은 문자열 길이가 선형이어야하며 시퀀스가 ​​너무 반복적이지 않은 한 괜찮습니다 (이 경우 재귀를 while 루프로 바꿀 수 있음).

def find_all(st, substr, start_pos=0, accum=[]):
    ix = st.find(substr, start_pos)
    if ix == -1:
        return accum
    return find_all(st, substr, start_pos=ix + 1, accum=accum + [ix])

bstpierre의 list comprehension은 짧은 시퀀스에 대한 좋은 솔루션이지만 2 차 복잡도를 가지고 있고 내가 사용하던 긴 텍스트로 완성되지 않은 것 같습니다.

findall_lc = lambda txt, substr: [n for n in xrange(len(txt))
                                   if txt.find(substr, n) == n]

중요하지 않은 길이의 임의 문자열의 경우 두 함수는 동일한 결과를 제공합니다.

import random, string; random.seed(0)
s = ''.join([random.choice(string.ascii_lowercase) for _ in range(100000)])

>>> find_all(s, 'th') == findall_lc(s, 'th')
True
>>> findall_lc(s, 'th')[:4]
[564, 818, 1872, 2470]

하지만 2 차 버전은 약 300 배 더 느립니다.

%timeit find_all(s, 'th')
1000 loops, best of 3: 282 µs per loop

%timeit findall_lc(s, 'th')    
10 loops, best of 3: 92.3 ms per loop

#!/usr/local/bin python3
#-*- coding: utf-8 -*-

main_string = input()
sub_string = input()

count = counter = 0

for i in range(len(main_string)):
    if main_string[i] == sub_string[0]:
        k = i + 1
        for j in range(1, len(sub_string)):
            if k != len(main_string) and main_string[k] == sub_string[j]:
                count += 1
                k += 1
        if count == (len(sub_string) - 1):
            counter += 1
        count = 0

print(counter) 

This program counts the number of all substrings even if they are overlapped without the use of regex. But this is a naive implementation and for better results in worst case it is advised to go through either Suffix Tree, KMP and other string matching data structures and algorithms.


Here is my function for finding multiple occurrences. Unlike the other solutions here, it supports the optional start and end parameters for slicing, just like str.index:

def all_substring_indexes(string, substring, start=0, end=None):
    result = []
    new_start = start
    while True:
        try:
            index = string.index(substring, new_start, end)
        except ValueError:
            return result
        else:
            result.append(index)
            new_start = index + len(substring)

A simple iterative code which returns a list of indices where the substring occurs.

        def allindices(string, sub):
           l=[]
           i = string.find(sub)
           while i >= 0:
              l.append(i)
              i = string.find(sub, i + 1)
           return l

You can split to get relative positions then sum consecutive numbers in a list and add (string length * occurence order) at the same time to get the wanted string indexes.

>>> key = 'll'
>>> text = "Allowed Hello Hollow"
>>> x = [len(i) for i in text.split(key)[:-1]]
>>> [sum(x[:i+1]) + i*len(key) for i in range(len(x))]
[1, 10, 16]
>>> 

Maybe not so Pythonic, but somewhat more self-explanatory. It returns the position of the word looked in the original string.

def retrieve_occurences(sequence, word, result, base_counter):
     indx = sequence.find(word)
     if indx == -1:
         return result
     result.append(indx + base_counter)
     base_counter += indx + len(word)
     return retrieve_occurences(sequence[indx + len(word):], word, result, base_counter)

I think there's no need to test for length of text; just keep finding until there's nothing left to find. Like this:

    >>> text = 'Allowed Hello Hollow'
    >>> place = 0
    >>> while text.find('ll', place) != -1:
            print('ll found at', text.find('ll', place))
            place = text.find('ll', place) + 2


    ll found at 1
    ll found at 10
    ll found at 16

You can also do it with conditional list comprehension like this:

string1= "Allowed Hello Hollow"
string2= "ll"
print [num for num in xrange(len(string1)-len(string2)+1) if string1[num:num+len(string2)]==string2]
# [1, 10, 16]

I had randomly gotten this idea just a while ago. Using a While loop with string splicing and string search can work, even for overlapping strings.

findin = "algorithm alma mater alison alternation alpines"
search = "al"
inx = 0
num_str = 0

while True:
    inx = findin.find(search)
    if inx == -1: #breaks before adding 1 to number of string
        break
    inx = inx + 1
    findin = findin[inx:] #to splice the 'unsearched' part of the string
    num_str = num_str + 1 #counts no. of string

if num_str != 0:
    print("There are ",num_str," ",search," in your string.")
else:
    print("There are no ",search," in your string.")

I'm an amateur in Python Programming (Programming of any language, actually), and am not sure what other issues it could have, but I guess it's working fine?

I guess lower() could be used somewhere in it too if needed.

참고URL : https://stackoverflow.com/questions/3873361/finding-multiple-occurrences-of-a-string-within-a-string-in-python

반응형