python - programme - nombre d occurence d un caractère dans une chaine en c++



Trouver plusieurs occurrences d'une chaîne dans une chaîne en Python (12)

Comment puis-je trouver plusieurs occurrences d'une chaîne dans une chaîne en Python? Considère ceci:

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

Donc, la première occurrence de ll est à 1 comme prévu. Comment puis-je trouver la prochaine occurrence de celui-ci?

La même question est valable pour une liste. Considérer:

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

Comment puis-je trouver tous les ll avec leurs index?

https://ffff65535.com


Ce link explique comment faire le tout dans O (n) et inclut également une solution en python.

Si vous allez plus loin dans les ensembles de ' Suffix trees ' vous seriez capable de faire la même chose si vous aviez une grande chaîne mais que vous vouliez y rechercher des milliers de motifs.


Cela peut être fait en une ligne en utilisant des compréhensions de liste:

example = "a test am I"
indicies = [index for index, value in enumerate(example) if value == "a"]
print(indices)

 >>> [0, 7]

Une technique similaire fonctionne pour les listes:

example = ["a", "b", "c", "a", "d"]
indices = [index for index, value in enumerate(example) if value =="a"]
print(indices)

>>> [0, 3]

En utilisant des expressions régulières, vous pouvez utiliser re.finditer pour rechercher toutes les occurences (sans chevauchement):

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

Alternativement, si vous ne voulez pas l'overhead des expressions régulières, vous pouvez aussi utiliser str.find à plusieurs str.find pour obtenir l'index suivant :

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

Cela fonctionne également pour les listes et autres séquences.


FWIW, voici quelques alternatives non-RE qui, je pense, sont plus propres que la solution de Poke .

La première utilise str.index et vérifie 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

Le second test utilise str.find et vérifie la sentinelle de -1 en utilisant iter :

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)

Pour appliquer n'importe laquelle de ces fonctions à une liste, à un tuple ou à d'autres itérables de chaînes, vous pouvez utiliser une fonction de plus haut niveau - une fonction qui prend une fonction comme l'un de ses arguments - comme celle-ci:

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)

Je pense que ce que vous cherchez est string.count

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

J'espère que cela t'aides
NOTE: ceci ne capture que les occurrences qui ne se chevauchent pas


Peut-être pas si pythonique, mais un peu plus explicite. Il renvoie la position du mot recherché dans la chaîne d'origine.

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)

Pour votre exemple de liste:

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

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

Si vous vouliez tous les éléments d'une liste contenant 'll', vous pourriez aussi le faire.

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

Tout nouveau à la programmation en général et en travaillant à travers un tutoriel en ligne. On m'a demandé de faire cela aussi, mais en utilisant seulement les méthodes que j'avais apprises jusqu'ici (essentiellement des cordes et des boucles). Je ne sais pas si cela ajoute de la valeur ici, et je sais que ce n'est pas comme ça que vous le feriez, mais je l'ai eu pour ça:

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)

Voici ma fonction pour trouver plusieurs occurrences. Contrairement aux autres solutions, il prend en charge les paramètres facultatifs de début et de fin pour le découpage, tout comme 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)

Vous pouvez également le faire avec une compréhension de liste conditionnelle comme ceci:

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]

#!/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) 

Ce programme compte le nombre de toutes les sous-chaînes même si elles sont superposées sans l'utilisation de regex. Mais il s'agit d'une implémentation naïve et pour de meilleurs résultats dans le pire des cas, il est conseillé de passer par Suffix Tree, KMP et d'autres structures de données et algorithmes correspondants.


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




string