Sprawdź, czy istnieje wiele ciągów w innym ciągu


378

Jak mogę sprawdzić, czy którykolwiek z ciągów w tablicy istnieje w innym ciągu?

Lubić:

a = ['a', 'b', 'c']
str = "a123"
if a in str:
  print "some of the strings found in str"
else:
  print "no strings found in str"

Ten kod nie działa, po prostu pokazuje, co chcę osiągnąć.


5
Dziwię się, że nie ma (jeszcze) żadnych odpowiedzi w porównaniu do skompilowanego wyrażenia regularnego pod względem perf, szczególnie w porównaniu z rozmiarem łańcucha i liczbą „igieł” do wyszukania.
Pat

3
@Pat Nie jestem zaskoczony. Pytanie nie dotyczy wydajności. Obecnie większość programistów bardziej zależy na tym, aby to zrobić i na czytelności. Pytanie dotyczące wydajności jest prawidłowe, ale inne pytanie.
guettli

13
Używanie str jako zmiennej jest mylące i może powodować nieoczekiwane zachowanie, ponieważ jest słowem zastrzeżonym; patrz link .
Clever Guy

regex [abc]działa również doskonale i będzie szybszy, jeśli będzie więcej niż kilku kandydatów do przetestowania. Ale jeśli ciągi są dowolne i nie znasz ich wcześniej, aby utworzyć wyrażenie regularne, będziesz musiał zastosować to any(x in str for x in a)podejście.
smci

@CleverGuy Masz rację, choć nie jest to słowo zastrzeżone, w przeciwnym razie nie będziesz mógł do niego przypisać. To jest wbudowane.
wjandrea

Odpowiedzi:


717

Możesz użyć any:

a_string = "A string is more than its parts!"
matches = ["more", "wholesome", "milk"]

if any(x in a_string for x in matches):

Podobnie, aby sprawdzić, czy znaleziono wszystkie ciągi z listy, użyj allzamiast any.


11
any () wymaga iteracji. Nie jestem pewien, jakiej wersji Pythona używasz, ale w 2.6 będziesz musiał umieścić [] wokół swojego argumentu na dowolnym (). dowolne ([x w str dla x w a]), dzięki czemu zrozumienie zwraca iterowalną wartość. Ale może nowsze wersje Pythona już to robią.
emispowder

7
@ Mark Byers: Przepraszam za późny komentarz, ale czy istnieje sposób na wydrukowanie znalezionego ciągu? Jak byś to zrobił? Dziękuję Ci.
Shankar Kumar

3
Nie jestem pewien, czy rozumiem, jeśli a to lista, a str to coś, z czym można się równać, jakie jest x? Python newbie ftw. :)
czerwony

2
@red: możesz czytać for x in ajak „dla każdego elementu na liście”. Ponieważ ajest to lista ciągów i xjest elementem tej listy, xjest ciągiem (jeden z „a”, „b”, „c” w oryginalnym przykładzie)
użytkownik

6
@ emispowder Działa dla mnie tak jak jest w Pythonie 2.6.9.
MPlanchard,

67

any()jest zdecydowanie najlepszym podejściem, jeśli wszystko, czego chcesz, to Truelub False, ale jeśli chcesz wiedzieć, który łańcuch / ciągi pasują, możesz użyć kilku rzeczy.

Jeśli chcesz pierwszego dopasowania (z Falsedomyślnie):

match = next((x for x in a if x in str), False)

Jeśli chcesz uzyskać wszystkie dopasowania (w tym duplikaty):

matches = [x for x in a if x in str]

Jeśli chcesz uzyskać wszystkie niedubliczne dopasowania (bez względu na kolejność):

matches = {x for x in a if x in str}

Jeśli chcesz uzyskać wszystkie niedubliczne mecze we właściwej kolejności:

matches = []
for x in a:
    if x in str and x not in matches:
        matches.append(x)

dodaj też przykład ostatniego meczu
Oleg Kokorin

@OlegKokorin: Tworzy listę pasujących ciągów w tej samej kolejności, w jakiej je znajduje, ale zachowuje tylko pierwszy, jeśli dwa są takie same.
zondo

Korzystanie z OrderedDictjest prawdopodobnie bardziej wydajne niż lista. Zobacz tę odpowiedź na temat „Usuwanie duplikatów z list”
wjandrea

44

Należy zachować ostrożność, jeśli struny są dłuższe alub strdłuższe. Proste rozwiązania przyjmują O (S * (A ^ 2)), gdzie Sjest długością, stra A jest sumą długości wszystkich łańcuchów a. Aby uzyskać szybsze rozwiązanie, spójrz na algorytm Aho-Corasicka do dopasowywania ciągów, który działa w czasie liniowym O (S + A).


czy Aho-Corasick może również znaleźć podciągi zamiast przedrostków?
RetroCode,

1
Niektóre biblioteki Pythona Aho-Corasicka są tu i tutaj
vorpal

23

Aby dodać trochę różnorodności dzięki regex:

import re

if any(re.findall(r'a|b|c', str, re.IGNORECASE)):
    print 'possible matches thanks to regex'
else:
    print 'no matches'

lub jeśli twoja lista jest za długa - any(re.findall(r'|'.join(a), str, re.IGNORECASE))


1
Działa to dla danego przypadku użycia pytania. Jeśli szukasz (lub *to się nie powiedzie, ponieważ należy wykonać cytowanie składni wyrażenia regularnego.
guettli

2
W razie potrzeby możesz uciec '|'.join(map(re.escape, strings_to_match)). Prawdopodobnie re.compile('|'.join(...))również.
Artyer

12

Musisz iterować po elementach.

a = ['a', 'b', 'c']
str = "a123"
found_a_string = False
for item in a:    
    if item in str:
        found_a_string = True

if found_a_string:
    print "found a match"
else:
    print "no match found"

2
Tak, wiedziałem, jak to zrobić, ale w porównaniu z odpowiedzią Marka, to okropny kod.
jahmax

10
Tylko jeśli rozumiesz kod Marka. Problem polegał na tym, że nie badałeś elementów swojej tablicy. Istnieje wiele zwięzłych, pytonicznych sposobów na osiągnięcie tego, co chcesz, co ukryłoby istotę tego, co było nie tak z twoim kodem.
Seamus Campbell

9
Może to być „okropny kod”, ale właśnie to robi dowolna () . Daje to również pasujący ciąg znaków, podczas gdy dowolny () informuje tylko o zgodności.
alldayremix

4

jbernadas wspomniał już o algorytmie Aho-Corasicka w celu zmniejszenia złożoności.

Oto jeden ze sposobów użycia go w Pythonie:

  1. Pobierz aho_corasick.py stąd

  2. Umieść go w tym samym katalogu, co główny plik Python i nazwij go aho_corasick.py

  3. Wypróbuj alrorithm z następującym kodem:

    from aho_corasick import aho_corasick #(string, keywords)
    
    print(aho_corasick(string, ["keyword1", "keyword2"]))

Pamiętaj, że w wyszukiwaniu rozróżniana jest wielkość liter


3
a = ['a', 'b', 'c']
str =  "a123"

a_match = [True for match in a if match in str]

if True in a_match:
  print "some of the strings found in str"
else:
  print "no strings found in str"

1

To zależy od kontekstu, załóżmy, jeśli chcesz sprawdzić pojedynczy dosłownym jak każdy pojedynczy wyraz (A, E, W, .. etc) w wystarczy

original_word ="hackerearcth"
for 'h' in original_word:
      print("YES")

jeśli chcesz zaznaczyć dowolny znak spośród słowa oryginalnego: skorzystaj z

if any(your_required in yourinput for your_required in original_word ):

jeśli chcesz wszystkich danych wejściowych w tym oryginalnym słowie, skorzystaj ze wszystkich prostych

original_word = ['h', 'a', 'c', 'k', 'e', 'r', 'e', 'a', 'r', 't', 'h']
yourinput = str(input()).lower()
if all(requested_word in yourinput for requested_word in original_word):
    print("yes")

Jaki byłby twój wkład? Potrafię rozpoznać dwie rzeczy: zdanie, w którym czegoś szukam. Szereg słów, których szukam. Ale ty opisujesz trzy zmienne, a ja nie mogę zrozumieć, co to trzecia.
mayid

1

Po prostu więcej informacji o tym, jak uzyskać wszystkie elementy listy dostępne w String

a = ['a', 'b', 'c']
str = "a123" 
list(filter(lambda x:  x in str, a))

1

Zaskakująco szybkie podejście polega na użyciu set:

a = ['a', 'b', 'c']
str = "a123"
if set(a) & set(str):
    print("some of the strings found in str")
else:
    print("no strings found in str")

Działa to, jeśli anie zawiera wartości wieloznakowych (w takim przypadku należy użyć, anyjak podano powyżej ). Jeśli tak, to prościej określić ajako ciąg: a = 'abc'.


0
flog = open('test.txt', 'r')
flogLines = flog.readlines()
strlist = ['SUCCESS', 'Done','SUCCESSFUL']
res = False
for line in flogLines:
     for fstr in strlist:
         if line.find(fstr) != -1:
            print('found') 
            res = True


if res:
    print('res true')
else: 
    print('res false')

przykładowy obraz wyjściowy


0

Użyłbym tego rodzaju funkcji do prędkości:

def check_string(string, substring_list):
    for substring in substring_list:
        if substring in string:
            return True
    return False

0
data = "firstName and favoriteFood"
mandatory_fields = ['firstName', 'lastName', 'age']


# for each
for field in mandatory_fields:
    if field not in data:
        print("Error, missing req field {0}".format(field));

# still fine, multiple if statements
if ('firstName' not in data or 
    'lastName' not in data or
    'age' not in data):
    print("Error, missing a req field");

# not very readable, list comprehension
missing_fields = [x for x in mandatory_fields if x not in data]
if (len(missing_fields)>0):
    print("Error, missing fields {0}".format(", ".join(missing_fields)));
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.