Python - sprawdź, czy słowo jest w ciągu

177

Pracuję z Pythonem v2 i próbuję dowiedzieć się, czy możesz stwierdzić, czy słowo znajduje się w ciągu.

Znalazłem informacje na temat identyfikowania, czy słowo znajduje się w ciągu - używając .find, ale czy istnieje sposób na wykonanie instrukcji IF. Chciałbym mieć coś takiego:

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

Dzięki za wszelką pomoc.

Woo
źródło

Odpowiedzi:

349

Co jest nie tak z:

if word in mystring: 
   print 'success'
fabrizioM
źródło
103
tylko jako ostrzeżenie, jeśli masz ciąg „paratyfus jest zły” i zrobisz, jeśli „dur brzuszny” w „paratyfus jest zły”, otrzymasz prawdę.
David Nelson,
3
Czy ktoś wie, jak rozwiązać ten problem?
user2567857
4
@ user2567857, wyrażenia regularne - zobacz odpowiedź Hugh Bothwella.
Mark Rajcok
4
if (słowo1 w mystringu i słowo2 w mystringu)
louie mcconnell
2
Jak to jest akceptowana odpowiedź? !! Po prostu sprawdza, czy sekwencja znaków (a nie słowo) pojawia się w ciągu
pedram bashiri
168
if 'seek' in 'those who seek shall find':
    print('Success!')

ale pamiętaj, że pasuje to do sekwencji znaków, niekoniecznie do całego słowa - na przykład 'word' in 'swordsmith'jest True. Jeśli chcesz dopasować tylko całe słowa, powinieneś użyć wyrażeń regularnych:

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
źródło
3
Czy istnieje naprawdę szybka metoda wyszukiwania wielu słów, powiedzmy zestawu kilku tysięcy słów, bez konieczności konstruowania pętli for przechodzącej przez każde słowo? Mam milion zdań i milion terminów do przeszukania, aby sprawdzić, które zdanie ma które pasujące słowa. Obecnie przetwarzanie danych zajmuje mi kilka dni i chcę wiedzieć, czy istnieje szybszy sposób.
Tom
@Tom spróbuj użyć grepa zamiast wyrażenia regularnego Pythona
El Ruso
p1 dla miecznika
Robino
Jak radzisz sobie z wyjątkami, np. Gdy słowo nie znajduje się w ciągu?
FaCoffee
1
@FaCoffee: jeśli ciąg nie zostanie znaleziony, funkcja zwraca None (patrz ostatni przykład powyżej).
Hugh Bothwell
48

Jeśli chcesz dowiedzieć się, czy całe słowo znajduje się na liście słów oddzielonych spacjami, po prostu użyj:

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

Ta elegancka metoda jest również najszybsza. W porównaniu z podejściami Hugh Bothwella i daSonga:

>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

Edycja: niewielki wariant tego pomysłu dla Pythona 3.6+, równie szybki:

def contains_word(s, w):
    return f' {w} ' in f' {s} '
user200783
źródło
3
To moja ulubiona odpowiedź :)
IanS
Zgadzam się, ale najszybsze rozwiązanie nie ignoruje przypadków, takich jak re. Stos (... tak.
Michael Smith
7
Z tym wiąże się kilka problemów: (1) Słowa na końcu (2) Słowa na początku (3) słowa między nimi, takie jakcontains_word("says", "Simon says: Don't use this answer")
Martin Thoma
@MartinThoma - Jak już wspomniano, ta metoda służy do sprawdzania „czy całe słowo znajduje się na liście słów oddzielonych spacjami”. W takiej sytuacji działa dobrze w przypadku: (1) słów na końcu (2) słów na początku (3) słów pomiędzy. Twój przykład zawodzi tylko dlatego, że lista słów zawiera dwukropek.
user200783
1
@JeffHeaton Ponownie, ta metoda jest SZCZEGÓLNIE dla „Jeśli chcesz dowiedzieć się, czy całe słowo znajduje się na liście słów oddzielonych spacjami”, jak wyraźnie stwierdził autor.
bitwitch
17

find zwraca liczbę całkowitą reprezentującą indeks miejsca znalezienia elementu wyszukiwania. Jeśli nie zostanie znaleziony, zwraca -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
źródło
13

Możesz podzielić ciąg na słowa i sprawdzić listę wyników.

if word in string.split():
    print 'success'
Corvax
źródło
3
Skorzystaj z linku edycji, aby wyjaśnić, jak działa ten kod, a nie tylko podawać kod, ponieważ wyjaśnienie może pomóc przyszłym czytelnikom.
Jed Fox
1
To powinna być właściwa odpowiedź na dopasowanie całego słowa.
Kaushik NP,
10

Ta niewielka funkcja porównuje wszystkie wyszukiwane słowa w podanym tekście. Jeśli wszystkie wyszukiwane słowa znajdują się w tekście, zwraca długość wyszukiwania lubFalse inny sposób.

Obsługuje również wyszukiwanie ciągów znaków 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

stosowanie:

find_words('çelik güray ankara', 'güray ankara')
Guray Celik
źródło
8

Jeśli dopasowanie sekwencji znaków nie jest wystarczające i musisz dopasować całe słowa, oto prosta funkcja, która wykonuje zadanie. Zasadniczo dodaje spacje w razie potrzeby i wyszukuje je w ciągu:

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

Zakłada się, że przecinki i inne znaki interpunkcyjne zostały już usunięte.

daSong
źródło
To rozwiązanie działało najlepiej w moim przypadku, ponieważ używam tokenizowanych ciągów oddzielonych spacjami.
Avijit,
4

Ponieważ pytasz o słowo, a nie o string, chciałbym przedstawić rozwiązanie, które nie jest wrażliwe na przedrostki / sufiksy i ignoruje wielkość liter:

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

Jeśli twoje słowa mogą zawierać specjalne znaki regex (takie jak +), potrzebujeszre.escape(word)

Martin Thoma
źródło
3

Zaawansowany sposób sprawdzenia dokładnego słowa, które musimy znaleźć w długim ciągu:

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
źródło
3

Użycie wyrażenia regularnego jest rozwiązaniem, ale jest to zbyt skomplikowane w takim przypadku.

Możesz po prostu podzielić tekst na listę słów. Użyj do tego metody split ( separator , num ) . Zwraca listę wszystkich słów w ciągu, używając separatora jako separatora. Jeśli separator jest nieokreślony, dzieli się na wszystkie białe znaki (opcjonalnie możesz ograniczyć liczbę podziałów do num ).

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

To nie zadziała w przypadku ciągów z przecinkami itp. Na przykład:

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

Jeśli chcesz również podzielić wszystkie przecinki itp., Użyj argumentu separatora w ten sposób:

# 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
źródło
1
Jest to dobre rozwiązanie, podobne do @Corvax, z zaletą dodawania wspólnych znaków do podziału, tak aby w ciągu znaków typu „First: there ..” można było znaleźć słowo „First”. Zauważ, że @tstempko nie zawiera ":" w dodatkowych znakach. Ja bym :). Ponadto, jeśli wyszukiwanie nie uwzględnia wielkości liter, rozważ użycie .lower () zarówno w słowie, jak i w ciągu przed podziałem. mystring.lower().split()i word.lower() myślę, że jest to również szybsze niż przykład wyrażenia regularnego.
beauk
0

Możesz po prostu dodać spację przed i po „słowie”.

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

W ten sposób szuka spacji przed i po „słowie”.

>>> Type your word: Swordsmith
>>> Nope
>>> Type your word:  word 
>>> Yes
PyGuy
źródło
2
Ale co, jeśli słowo znajduje się na początku lub na końcu zdania (bez spacji)
MikeL