ตรวจสอบว่ามีหลายสตริงอยู่ในสตริงอื่นหรือไม่


378

ฉันจะตรวจสอบว่ามีสตริงใด ๆ ในอาร์เรย์อยู่ในสตริงอื่นได้อย่างไร

ชอบ:

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"

รหัสนั้นใช้งานไม่ได้มันเป็นเพียงการแสดงสิ่งที่ฉันต้องการให้บรรลุ


5
ฉันประหลาดใจที่ไม่มีคำตอบใด ๆ ที่เปรียบเทียบกับ regex ที่รวบรวมในแง่ของ perf โดยเฉพาะเมื่อเปรียบเทียบกับขนาดของสตริงและจำนวนของ "needles" เพื่อค้นหา
Pat

3
@ Pat ฉันไม่แปลกใจเลย คำถามไม่ได้เกี่ยวกับประสิทธิภาพ วันนี้โปรแกรมเมอร์ส่วนใหญ่ใส่ใจกับการทำและอ่านง่าย คำถามเรื่องประสิทธิภาพถูกต้อง แต่เป็นคำถามที่แตกต่าง
guettli

13
การใช้ str เป็นตัวแปรทำให้เกิดความสับสนและอาจส่งผลให้เกิดพฤติกรรมที่ไม่คาดคิดเนื่องจากเป็นคำสงวน ดูการเชื่อมโยง
Guy Clever

regex [abc]ยังทำงานได้อย่างสมบูรณ์แบบและจะเร็วขึ้นหากมีผู้สมัครสอบมากกว่าสองคน แต่ถ้าสตริงนั้นเป็นกฎเกณฑ์และคุณไม่รู้จักมันล่วงหน้าเพื่อสร้าง regex คุณจะต้องใช้any(x in str for x in a)วิธีนี้
smci

@CleverGuy คุณพูดถูกแม้ว่ามันจะไม่ใช่คำที่สงวนไว้มิฉะนั้นคุณจะไม่สามารถมอบหมายให้กับมันได้ มันเป็นแบบในตัว
wjandrea

คำตอบ:


717

คุณสามารถใช้any:

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

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

ในทำนองเดียวกันการตรวจสอบว่าทุกสายจากรายการจะพบว่าใช้แทนallany


11
any () ทำซ้ำได้ ฉันไม่แน่ใจว่าคุณใช้ Python เวอร์ชันใด แต่ใน 2.6 คุณจะต้องใส่ [] รอบ ๆ อาร์กิวเมนต์ของคุณไปที่ () ใด ๆ ([x ใน str สำหรับ x ใน a]) เพื่อให้ความเข้าใจส่งคืน iterable แต่บางที Python รุ่นที่ใหม่กว่าอาจทำสิ่งนี้ไปแล้ว
emispowder

7
@ Mark Byers: ขออภัยในความคิดเห็นที่ล่าช้า แต่มีวิธีพิมพ์สตริงที่พบหรือไม่ คุณจะทำอย่างไร ขอบคุณ.
Shankar Kumar

3
ไม่แน่ใจว่าฉันเข้าใจหรือไม่ถ้า a คือรายการและ str คือสิ่งที่ต้องเทียบกับ x คืออะไร Python newbie ftw :)
แดง

2
@ แดง: คุณสามารถอ่านfor x in aเช่น "สำหรับแต่ละองค์ประกอบในรายการ" เนื่องจากaเป็นรายการของสตริงและxเป็นองค์ประกอบของรายการxนั้นเป็นสตริง (หนึ่งใน 'a', 'b', 'c' ในตัวอย่างดั้งเดิม)
ผู้ใช้

6
@emispowder มันทำงานได้ดีสำหรับฉันตามที่เป็นใน Python 2.6.9
MPlanchard

67

any()คือไกลโดยวิธีที่ดีที่สุดถ้าสิ่งที่คุณต้องการคือTrueหรือFalseแต่ถ้าคุณต้องการที่จะรู้เฉพาะซึ่งสตริง / สตริงตรงกับคุณสามารถใช้สองสิ่ง

หากคุณต้องการนัดแรก (พร้อมFalseเป็นค่าเริ่มต้น):

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

หากคุณต้องการได้รับการแข่งขันทั้งหมด (รวมถึงรายการที่ซ้ำกัน):

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

หากคุณต้องการที่จะได้รับการแข่งขันที่ไม่ซ้ำกันทั้งหมด (คำสั่งไม่สนใจ):

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

หากคุณต้องการได้รับการแข่งขันที่ไม่ซ้ำกันทั้งหมดในลำดับที่ถูกต้อง:

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

โปรดเพิ่มตัวอย่างสำหรับการแข่งขันครั้งสุดท้ายด้วย
Oleg Kokorin

@OlegKokorin: มันสร้างรายการของสตริงที่ตรงกันในลำดับเดียวกันกับที่พบพวกมัน แต่มันจะเก็บเฉพาะอันแรกถ้าทั้งสองเหมือนกัน
zondo

การใช้งานOrderedDictอาจมีประสิทธิภาพมากกว่ารายการ ดูคำตอบนี้ใน "การลบรายการที่ซ้ำกันในรายการ"
wjandrea

44

คุณควรระวังหากสายอักขระนั้นยาวaหรือstrยาวขึ้น โซลูชั่นตรงไปตรงมาใช้ O (S * (A ^ 2)) ซึ่งSคือความยาวของstrและ A คือผลรวมของ lenghts aของสตริงทั้งหมดในที่ สำหรับวิธีแก้ปัญหาที่รวดเร็วกว่าดูที่Aho-Corasickอัลกอริทึมสำหรับการจับคู่สตริงซึ่งทำงานในเวลาเชิงเส้น O (S + A)


Aho-Corasick สามารถหาสตริงย่อยแทนคำนำหน้าได้หรือไม่
RetroCode

1
งูหลาม Aho-Corasick ห้องสมุดบางอย่างอยู่ที่นี่และที่นี่
vorpal

23

เพียงเพิ่มความหลากหลายด้วยregex:

import re

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

หรือถ้ารายการของคุณยาวเกินไป - any(re.findall(r'|'.join(a), str, re.IGNORECASE))


1
สิ่งนี้ใช้ได้กับกรณีการใช้งานที่กำหนดของคำถาม หากคุณค้นหา(หรือ*สิ่งนี้ล้มเหลวเนื่องจากการอ้างถึงไวยากรณ์ regex จำเป็นต้องทำ
guettli

2
'|'.join(map(re.escape, strings_to_match))คุณสามารถหลบหนีได้ถ้าจำเป็นด้วย คุณอาจจะre.compile('|'.join(...))เช่นกัน
Artyer

12

คุณจำเป็นต้องทำซ้ำในองค์ประกอบของ

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
ใช่ฉันรู้วิธีการทำเช่นนั้น แต่เมื่อเทียบกับคำตอบของ Marks นั่นเป็นรหัสที่น่ากลัว
jahmax

10
เฉพาะในกรณีที่คุณเข้าใจรหัสของมาร์ค ปัญหาที่คุณมีคือคุณไม่ได้ตรวจสอบองค์ประกอบของอาร์เรย์ มีวิธีการสรุปสั้น ๆ มากมายที่จะทำให้สิ่งที่คุณต้องการสำเร็จซึ่งจะซ่อนสาระสำคัญของสิ่งที่ผิดกับรหัสของคุณ
เชมัสแคมป์เบล

9
มันอาจจะเป็น 'รหัสที่น่ากลัว แต่มันเป็นสิ่งใด () ไม่ นอกจากนี้ยังให้สตริงที่แท้จริงที่ตรงกับในขณะที่ใด ๆ () เพียงแค่บอกคุณว่ามีการแข่งขัน
alldayremix

4

jbernadas ได้กล่าวถึงAho-Corasick-Algorithmเพื่อลดความซับซ้อน

นี่เป็นวิธีหนึ่งในการใช้งานใน Python:

  1. ดาวน์โหลด aho_corasick.py จากที่นี่

  2. วางไว้ในไดเรกทอรีเดียวกับไฟล์ Python หลักของคุณและตั้งชื่อ aho_corasick.py

  3. ลองใช้ alrorithm ด้วยรหัสต่อไปนี้:

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

โปรดทราบว่าการค้นหาเป็นกรณี ๆ ไป


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

มันขึ้นอยู่กับบริบทสมมติว่าถ้าคุณต้องการตรวจสอบตัวอักษรเดียวเช่น (คำเดียวใด ๆ , e, w, .. ฯลฯ ) ในก็เพียงพอแล้ว

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

หากคุณต้องการตรวจสอบอักขระใด ๆ ใน original_word: ใช้ประโยชน์จาก

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

หากคุณต้องการอินพุตทั้งหมดที่คุณต้องการใน original_word นั้นให้ใช้ประโยชน์จากทั้งหมด

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

อะไรคือสิ่งที่คุณใส่ ฉันจำได้สองสิ่ง: ประโยคที่ฉันกำลังมองหาบางอย่าง อาร์เรย์ของคำที่ฉันกำลังมองหา แต่คุณอธิบายตัวแปรสามตัวและฉันไม่สามารถเข้าใจได้ว่าตัวแปรตัวที่สามคืออะไร
mayid

1

ข้อมูลเพิ่มเติมเกี่ยวกับวิธีรับองค์ประกอบรายการทั้งหมดที่มีอยู่ใน String

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

1

วิธีที่รวดเร็วอย่างไม่น่าเชื่อคือการใช้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")

สามารถใช้งานได้หากaไม่มีค่าหลายตัวอักษร (ในกรณีที่ใช้anyตามที่ระบุข้างต้น ) ถ้าเป็นเช่นนั้นก็ง่ายที่จะระบุเป็นสตริง:aa = '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')

ภาพตัวอย่างออก


0

ฉันจะใช้ฟังก์ชั่นชนิดนี้เพื่อความเร็ว:

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)));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.