จะตรวจสอบได้อย่างไรว่ารายการต่อไปนี้ทั้งหมดอยู่ในรายการหรือไม่?


115

ฉันพบว่ามีคำถามที่เกี่ยวข้องเกี่ยวกับวิธีค้นหาว่ามีอย่างน้อยหนึ่งรายการในรายการหรือไม่: จะตรวจสอบได้อย่างไรว่ามีรายการใดรายการ
หนึ่งต่อไปนี้อยู่ในรายการหรือไม่?

แต่วิธีที่ดีที่สุดและไพโธนิกในการค้นหาว่ามีรายการทั้งหมดอยู่ในรายการหรือไม่?

การค้นหาเอกสารฉันพบวิธีแก้ปัญหานี้:

>>> l = ['a', 'b', 'c']
>>> set(['a', 'b']) <= set(l)
True
>>> set(['a', 'x']) <= set(l)
False

ทางออกอื่น ๆ จะเป็นดังนี้:

>>> l = ['a', 'b', 'c']
>>> all(x in l for x in ['a', 'b'])
True
>>> all(x in l for x in ['a', 'x'])
False

แต่ที่นี่คุณต้องพิมพ์มากขึ้น

มีวิธีแก้ไขอื่น ๆ หรือไม่?


5
เกิดอะไรขึ้นset(smaller) <= set(larger)?
eumiro

1
ฉันคิดว่าโซลูชันที่สองของคุณที่มี 'ทั้งหมด' นั้นดูดีและน่ากลัวสำหรับฉัน
Jiho Noh

คำตอบ:


158

<=โดยทั่วไปแล้วตัวดำเนินการเช่นใน Python จะไม่เขียนทับเพื่อให้มีความหมายแตกต่างจาก "น้อยกว่าหรือเท่ากับ" อย่างมีนัยสำคัญ เป็นเรื่องผิดปกติที่ไลบรารีมาตรฐานทำเช่นนี้ - มีกลิ่นเหมือน API เดิมสำหรับฉัน

ใช้เมธอดที่เทียบเท่าและมีชื่อชัดเจนกว่า, set.issubset. โปรดทราบว่าคุณไม่จำเป็นต้องแปลงอาร์กิวเมนต์เป็นเซต มันจะทำเพื่อคุณถ้าจำเป็น

set(['a', 'b']).issubset(['a', 'b', 'c'])

2
ไม่ทราบว่าคุณสามารถส่งผ่านรายการโดยตรงเป็นอาร์กิวเมนต์ของ issubset ... ดี!
tsimbalar

1
แม้ว่าฉันจะเห็นด้วยกับความเชื่อมั่น แต่ฉันก็ค่อนข้างโอเคกับความคิด<=และissubsetความหมายในสิ่งเดียวกัน ทำไมคุณถึงไม่ชอบมัน?
Kirk Strauser

2
@Just: โดยพื้นฐานแล้วเนื่องจากไม่ชัดเจนว่า<=หมายถึงชุดใดโดยไม่ต้องค้นหาในเอกสารหรือมีความรู้มาก่อนว่ามันหมายถึงอะไรในทฤษฎีเซตในขณะที่ทุกคนรู้ว่าความissubsetหมายโดยอัตโนมัติ
Glenn Maynard

2
คุณรู้จักตัวดำเนินการทางคณิตศาสตร์สำหรับเซตย่อย (ไม่เหมาะสม) หรือไม่? โดยทั่วไปแล้วมันดูเหมือนกลม <=;)
dom0

รักโซลูชันนี้ มีวิธีรับตำแหน่งดัชนีหรือค่ารายการแทนบูล (True: False) หรือไม่?
Vlad Gulin

62

ฉันอาจจะใช้setในลักษณะต่อไปนี้:

set(l).issuperset(set(['a','b'])) 

หรือในทางกลับกัน:

set(['a','b']).issubset(set(l)) 

ฉันคิดว่ามันอ่านง่ายกว่าเล็กน้อย แต่มันอาจจะฆ่ามากเกินไป ชุดมีประโยชน์อย่างยิ่งในการคำนวณการรวมกัน / จุดตัด / ความแตกต่างระหว่างคอลเลกชัน แต่อาจไม่ใช่ตัวเลือกที่ดีที่สุดในสถานการณ์นี้ ...


จริงMySet.issubset(MyOtherSet)และMySet <= MyOtherSetเหมือนกัน

1
@wok: โอ้ฉันไม่รู้ แต่ฉันคิดว่าไวยากรณ์ <= ค่อนข้างสับสนเนื่องจากไวยากรณ์ที่คล้ายกันสามารถใช้กับรายการได้ แต่มีความหมายที่แตกต่างกันมาก
tsimbalar

3
มันไม่น่าสับสนจริงๆถ้าคุณจำได้ว่าการรวมกำหนดลำดับบางส่วนในชุดของชุด จริง ๆ แล้วมันสับสนเล็กน้อยที่<=มีความหมายสำหรับลำดับ: เราอาจคาดหวังว่ามันจะหมายถึง 'เป็นลำดับต่อมา' มากกว่าการเรียงลำดับตามศัพท์
aaronasterling

1
@aaronasterling: อืมโดยส่วนตัวฉันไม่คิดมากเกี่ยวกับ "ลำดับบางส่วน" เมื่อฉันพิมพ์รหัส :-) แต่ฉันเห็นด้วยกับความจริงที่ว่าการใช้<=กับลำดับก็รู้สึกแปลก ๆ เช่นกัน ...
tsimbalar

3
ฉันพบ gotcha เล็กน้อยที่นี่ฉันอยากจะพูดถึง: หากคุณใช้วิธีนี้คุณกำลังแปลงรายการของคุณเป็นชุดซึ่งหมายความว่าไม่มีรายการที่ซ้ำกัน ผลตอบแทนset(['a','a']).issubset(['a']) True
Orangestar

11

ฉันชอบสองสิ่งนี้เพราะมันดูสมเหตุสมผลที่สุดอันหลังสั้นกว่าและอาจเร็วที่สุด (แสดงที่นี่โดยใช้setไวยากรณ์ตัวอักษรซึ่งถูก ย้อนกลับไปที่ Python 2.7):

all(x in {'a', 'b', 'c'} for x in ['a', 'b'])
#   or
{'a', 'b'}.issubset({'a', 'b', 'c'})

โซลูชัน "ทั้งหมด" จะเร็วที่สุดเมื่อคุณวัดด้วย timeit () นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
Attersson

3

จะเกิดอะไรขึ้นถ้ารายการของคุณมีรายการที่ซ้ำกันเช่นนี้:

v1 = ['s', 'h', 'e', 'e', 'p']
v2 = ['s', 's', 'h']

ชุดไม่มีรายการที่ซ้ำกัน ดังนั้นบรรทัดต่อไปนี้จะคืนค่า True

set(v2).issubset(v1)

หากต้องการนับรายการที่ซ้ำกันคุณสามารถใช้รหัส:

v1 = sorted(v1)
v2 = sorted(v2)


def is_subseq(v2, v1):
    """Check whether v2 is a subsequence of v1."""
    it = iter(v1)
    return all(c in it for c in v2) 

ดังนั้นบรรทัดต่อไปนี้จะคืนค่า False

is_subseq(v2, v1)

1

นี่คือสิ่งที่ฉันค้นหาทางออนไลน์ แต่น่าเสียดายที่ไม่พบทางออนไลน์ แต่ในขณะที่ทดลองใช้ python interpreter

>>> case  = "caseCamel"
>>> label = "Case Camel"
>>> list  = ["apple", "banana"]
>>>
>>> (case or label) in list
False
>>> list = ["apple", "caseCamel"]
>>> (case or label) in list
True
>>> (case and label) in list
False
>>> list = ["case", "caseCamel", "Case Camel"]
>>> (case and label) in list
True
>>>

และหากคุณมีรายการตัวแปรที่อยู่ในไฟล์ sublist variable

>>>
>>> list  = ["case", "caseCamel", "Case Camel"]
>>> label = "Case Camel"
>>> case  = "caseCamel"
>>>
>>> sublist = ["unique banana", "very unique banana"]
>>>
>>> # example for if any (at least one) item contained in superset (or statement)
...
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
False
>>>
>>> sublist[0] = label
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>> # example for whether a subset (all items) contained in superset (and statement)
...
>>> # a bit of demorgan's law
...
>>> next((False for item in sublist if item not in list), True)
False
>>>
>>> sublist[1] = case
>>>
>>> next((False for item in sublist if item not in list), True)
True
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>>

0

ตัวอย่างวิธีการใช้นิพจน์แลมบ์ดาจะเป็นดังนี้:

issublist = lambda x, y: 0 in [_ in x for _ in y]

1
โปรดเพิ่มความคิดเห็นเพื่ออธิบาย / อธิบายคำตอบของคุณอย่างละเอียด
Sharad

0

ไม่ได้เป็นกรณี OP แต่ - สำหรับคนที่ต้องการที่จะแยกยืนยันในdicts และจบลงที่นี่เนื่องจาก googling ไม่ดี (เช่นผม) - คุณจำเป็นต้องทำงานร่วมกับdict.items:

>>> a = {'key': 'value'}
>>> b = {'key': 'value', 'extra_key': 'extra_value'}
>>> all(item in a.items() for item in b.items())
True
>>> all(item in b.items() for item in a.items())
False

นั่นเป็นเพราะdict.itemsส่งคืนทูเปิลของคู่คีย์ / ค่าและเหมือนกับอ็อบเจ็กต์ใด ๆ ใน Python ซึ่งเทียบเคียงกันได้

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