Python - Vérifier si Word est dans une chaîne

178

Je travaille avec Python v2 et j'essaie de savoir si vous pouvez dire si un mot est dans une chaîne.

J'ai trouvé des informations sur l'identification du mot dans la chaîne - en utilisant .find, mais y a-t-il un moyen de faire une instruction IF. J'aimerais avoir quelque chose comme ce qui suit:

if string.find(word):
    print 'success'

Merci pour toute aide.

Le Woo
la source

Réponses:

351

Qu'est-ce qui ne va pas chez:

if word in mystring: 
   print 'success'
fabrizioM
la source
103
juste comme une mise en garde, si vous avez une chaîne "paratyphoid is bad" et que vous faites un if "typhoid" in "paratyphoid is bad", vous obtiendrez un vrai.
David Nelson
3
Quelqu'un sait comment surmonter ce problème?
user2567857
4
@ user2567857, expressions régulières - voir la réponse de Hugh Bothwell.
Mark Rajcok
4
if (word1 dans mystring et word2 dans mystring)
louie mcconnell
2
Comment est-ce la réponse acceptée? !! Il vérifie simplement si une séquence de caractères (pas un mot) apparaît dans une chaîne
pedram bashiri
168
if 'seek' in 'those who seek shall find':
    print('Success!')

mais gardez à l'esprit que cela correspond à une séquence de caractères, pas nécessairement à un mot entier - par exemple, 'word' in 'swordsmith'est True. Si vous ne voulez faire correspondre que des mots entiers, vous devez utiliser des expressions régulières:

import re

def findWholeWord(w):
    return re.compile(r'\b({0})\b'.format(w), flags=re.IGNORECASE).search

findWholeWord('seek')('those who seek shall find')    # -> <match object>
findWholeWord('word')('swordsmith')                   # -> None
Hugh Bothwell
la source
3
Existe-t-il une méthode très rapide pour rechercher plusieurs mots, disons un ensemble de plusieurs milliers de mots, sans avoir à construire une boucle for passant par chaque mot? J'ai un million de phrases et un million de termes à rechercher pour voir quelle phrase a quels mots correspondants. Actuellement, le traitement me prend des jours et je veux savoir s'il existe un moyen plus rapide.
Tom
@Tom essaie d'utiliser grep au lieu de python regex
El Ruso
p1 for swordsmith
Robino
Comment gérez-vous les exceptions, par exemple lorsque le mot n'est pas trouvé dans la chaîne?
FaCoffee
1
@FaCoffee: si la chaîne n'est pas trouvée, la fonction renvoie None (voir le dernier exemple ci-dessus).
Hugh Bothwell
48

Si vous voulez savoir si un mot entier se trouve dans une liste de mots séparés par des espaces, utilisez simplement:

def contains_word(s, w):
    return (' ' + w + ' ') in (' ' + s + ' ')

contains_word('the quick brown fox', 'brown')  # True
contains_word('the quick brown fox', 'row')    # False

Cette méthode élégante est également la plus rapide. Par rapport aux approches de Hugh Bothwell et daSong:

>python -m timeit -s "def contains_word(s, w): return (' ' + w + ' ') in (' ' + s + ' ')" "contains_word('the quick brown fox', 'brown')"
1000000 loops, best of 3: 0.351 usec per loop

>python -m timeit -s "import re" -s "def contains_word(s, w): return re.compile(r'\b({0})\b'.format(w), flags=re.IGNORECASE).search(s)" "contains_word('the quick brown fox', 'brown')"
100000 loops, best of 3: 2.38 usec per loop

>python -m timeit -s "def contains_word(s, w): return s.startswith(w + ' ') or s.endswith(' ' + w) or s.find(' ' + w + ' ') != -1" "contains_word('the quick brown fox', 'brown')"
1000000 loops, best of 3: 1.13 usec per loop

Edit: Une légère variante de cette idée pour Python 3.6+, tout aussi rapide:

def contains_word(s, w):
    return f' {w} ' in f' {s} '
user200783
la source
3
C'est ma réponse préférée :)
IanS
Je suis d'accord, mais la solution la plus rapide n'ignore pas la casse comme re.compile (... fait.
Michael Smith
7
Cela pose plusieurs problèmes: (1) Mots à la fin (2) Mots au début (3) mots entre les deux commecontains_word("says", "Simon says: Don't use this answer")
Martin Thoma
@MartinThoma - Comme indiqué, cette méthode est spécifiquement pour savoir "si un mot entier est dans une liste de mots séparés par des espaces". Dans cette situation, cela fonctionne très bien pour: (1) les mots à la fin (2) les mots au début (3) les mots intermédiaires. Votre exemple échoue uniquement parce que votre liste de mots comprend un deux-points.
user200783
1
@JeffHeaton Encore une fois, cette méthode est SPÉCIFIQUEMENT pour "Si vous voulez savoir si un mot entier est dans une liste de mots séparés par des espaces", comme l'auteur l'a clairement indiqué.
bitwitch le
17

find renvoie un entier représentant l'index de l'endroit où l'élément de recherche a été trouvé. S'il n'est pas trouvé, il renvoie -1.

haystack = 'asdf'

haystack.find('a') # result: 0
haystack.find('s') # result: 1
haystack.find('g') # result: -1

if haystack.find(needle) >= 0:
  print 'Needle found.'
else:
  print 'Needle not found.'
Matt Howell
la source
13

Vous pouvez diviser la chaîne en mots et vérifier la liste des résultats.

if word in string.split():
    print 'success'
Corvax
la source
3
Veuillez utiliser le lien d' édition pour expliquer le fonctionnement de ce code et ne pas simplement donner le code, car une explication est plus susceptible d'aider les futurs lecteurs.
Jed Fox
1
Cela devrait être la vraie réponse pour faire correspondre le mot entier.
Kaushik NP
10

Cette petite fonction compare tous les mots recherchés dans un texte donné. Si tous les mots de recherche se trouvent dans le texte, renvoie la longueur de la recherche ou Falseautre.

Prend également en charge la recherche de chaînes Unicode.

def find_words(text, search):
    """Find exact words"""
    dText   = text.split()
    dSearch = search.split()

    found_word = 0

    for text_word in dText:
        for search_word in dSearch:
            if search_word == text_word:
                found_word += 1

    if found_word == len(dSearch):
        return lenSearch
    else:
        return False

usage:

find_words('çelik güray ankara', 'güray ankara')
Guray Celik
la source
8

Si la correspondance d'une séquence de caractères n'est pas suffisante et que vous devez faire correspondre des mots entiers, voici une fonction simple qui fait le travail. Il ajoute essentiellement des espaces si nécessaire et recherche cela dans la chaîne:

def smart_find(haystack, needle):
    if haystack.startswith(needle+" "):
        return True
    if haystack.endswith(" "+needle):
        return True
    if haystack.find(" "+needle+" ") != -1:
        return True
    return False

Cela suppose que les virgules et autres ponctuations ont déjà été supprimées.

daSong
la source
Cette solution a fonctionné le mieux pour mon cas car j'utilise des chaînes séparées par des espaces en jetons.
Avijit le
4

Comme vous demandez un mot et non une chaîne, je voudrais vous présenter une solution qui n'est pas sensible aux préfixes / suffixes et ignore la casse:

#!/usr/bin/env python

import re


def is_word_in_text(word, text):
    """
    Check if a word is in a text.

    Parameters
    ----------
    word : str
    text : str

    Returns
    -------
    bool : True if word is in text, otherwise False.

    Examples
    --------
    >>> is_word_in_text("Python", "python is awesome.")
    True

    >>> is_word_in_text("Python", "camelCase is pythonic.")
    False

    >>> is_word_in_text("Python", "At the end is Python")
    True
    """
    pattern = r'(^|[^\w]){}([^\w]|$)'.format(word)
    pattern = re.compile(pattern, re.IGNORECASE)
    matches = re.search(pattern, text)
    return bool(matches)


if __name__ == '__main__':
    import doctest
    doctest.testmod()

Si vos mots peuvent contenir des caractères spéciaux d'expression régulière (tels que +), vous devezre.escape(word)

Martin Thoma
la source
3

Méthode avancée pour vérifier le mot exact, que nous devons trouver dans une longue chaîne:

import re
text = "This text was of edited by Rock"
#try this string also
#text = "This text was officially edited by Rock" 
for m in re.finditer(r"\bof\b", text):
    if m.group(0):
        print "Present"
    else:
        print "Absent"
Rameez
la source
3

L'utilisation de regex est une solution, mais c'est trop compliqué dans ce cas.

Vous pouvez simplement diviser le texte en liste de mots. Utilisez la méthode split ( separator , num ) pour cela. Il renvoie une liste de tous les mots de la chaîne, en utilisant le séparateur comme séparateur. Si le séparateur n'est pas spécifié, il se divise sur tous les espaces (vous pouvez éventuellement limiter le nombre de divisions à num ).

list_of_words = mystring.split()
if word in list_of_words:
    print 'success'

Cela ne fonctionnera pas pour les chaînes avec des virgules, etc. Par exemple:

mystring = "One,two and three"
# will split into ["One,two", "and", "three"]

Si vous souhaitez également fractionner toutes les virgules, etc., utilisez un argument de séparation comme celui-ci:

# whitespace_chars = " \t\n\r\f" - space, tab, newline, return, formfeed
list_of_words = mystring.split( \t\n\r\f,.;!?'\"()")
if word in list_of_words:
    print 'success'
tstempko
la source
1
C'est une bonne solution, similaire à @Corvax, avec l'avantage d'ajouter des caractères communs à fractionner de sorte que dans une chaîne comme "First: there ..", le mot "First" puisse être trouvé. Notez que @tstempko n'inclut pas ":" dans les caractères supplémentaires. Je voudrais :). De plus, si la recherche ne respecte pas la casse, envisagez d'utiliser .lower () à la fois sur le mot et la chaîne avant le fractionnement. mystring.lower().split()et word.lower() je pense que c'est aussi plus rapide que l'exemple regex.
beauk
0

Vous pouvez simplement ajouter un espace avant et après "mot".

x = raw_input("Type your word: ")
if " word " in x:
    print "Yes"
elif " word " not in x:
    print "Nope"

De cette façon, il recherche l'espace avant et après "mot".

>>> Type your word: Swordsmith
>>> Nope
>>> Type your word:  word 
>>> Yes
PyGuy
la source
2
Mais que se passe-t-il si le mot est au début ou à la fin de la phrase (sans espace)
MikeL