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.

Odpowiedzi:


349

Co jest nie tak z:

if word in mystring: 
   print 'success'

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

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

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

13

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

if word in string.split():
    print 'success'

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

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.


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)


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"

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'

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

2
Ale co, jeśli słowo znajduje się na początku lub na końcu zdania (bez spacji)
— MikeL
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.