कई सेटों के प्रतिच्छेदन को खोजने का सबसे अच्छा तरीका है?


266

मेरे पास सेट की एक सूची है:

setlist = [s1,s2,s3...]

मुझे s1 want s2 ∩ s3 चाहिए ...

मैं इसे जोड़ीदार की एक श्रृंखला प्रदर्शन करके करने के लिए एक फ़ंक्शन लिख सकता हूं s1.intersection(s2), आदि।

क्या कोई अनुशंसित, बेहतर या अंतर्निहित तरीका है?

जवाबों:


454

पायथन संस्करण 2.6 से आप पर कई तर्कों का उपयोग कर सकते हैं set.intersection(), जैसे

u = set.intersection(s1, s2, s3)

यदि सेट एक सूची में हैं, तो इसका अनुवाद इस प्रकार होता है:

u = set.intersection(*setlist)

सूची विस्तार कहां *a_listहै

ध्यान दें कि set.intersectionहै नहीं एक स्थिर विधि है, लेकिन इस सूची के बाकी के साथ पहला सेट के चौराहे लागू करने के लिए कार्यात्मक संकेतन का उपयोग करता है। इसलिए यदि तर्क सूची खाली है तो यह विफल हो जाएगी।


65

2.6 के रूप में, set.intersectionमनमाने ढंग से कई पुनरावृत्तियों लेता है।

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])

24

स्पष्ट रूप set.intersectionसे आप यहां क्या चाहते हैं, लेकिन कभी भी आपको "इन सभी का योग", "इन सभी का उत्पाद ले लो", "इन सभी का xor लें", जो आप देख रहे हैं, के सामान्यीकरण की आवश्यकता है। reduceसमारोह:

from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

या

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

12

यदि आपके पास पायथन 2.6 या उच्चतर नहीं है, तो विकल्प लूप के लिए एक स्पष्ट लिखना है:

def set_list_intersection(set_list):
  if not set_list:
    return set()
  result = set_list[0]
  for s in set_list[1:]:
    result &= s
  return result

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])

आप यह भी उपयोग कर सकते हैं reduce:

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])

हालांकि, कई पायथन प्रोग्रामर इसे नापसंद करते हैं, जिसमें स्वयं गुइडो भी शामिल हैं :

लगभग 12 साल पहले, पायथन एक्वायर्ड लैम्ब्डा, कम (), फिल्टर () और मैप (), शिष्टाचार (मेरा मानना ​​है) एक लिस्प हैकर है जो उनसे चूक गया और काम करने वाले पैच प्रस्तुत किए। लेकिन, पीआर मूल्य के बावजूद, मुझे लगता है कि इन सुविधाओं को पायथन 3000 से काटा जाना चाहिए।

तो अब कम करें ()। यह वास्तव में वह है जिसे मैंने हमेशा सबसे अधिक नफरत किया है, क्योंकि, कुछ उदाहरणों के अलावा + या *, लगभग हर बार जब मैं एक गैर-तुच्छ फ़ंक्शन तर्क के साथ कम () कॉल देखता हूं, तो मुझे पेन और पेपर को हथियाने की आवश्यकता होती है आरेख क्या वास्तव में उस फ़ंक्शन में खिलाया जा रहा है इससे पहले कि मैं समझता हूं कि कम () क्या करना चाहिए। तो मेरे दिमाग में, कम करने की प्रयोज्यता () साहचर्य ऑपरेटरों के लिए बहुत सीमित है, और अन्य सभी मामलों में संचय लूप को स्पष्ट रूप से लिखना बेहतर है।


8
ध्यान दें कि गुइडो कहते हैं कि reduce"सहयोगी ऑपरेटरों के लिए सीमित है", जो इस मामले में लागू है। reduceयह पता लगाना बहुत मुश्किल है, लेकिन &इतना बुरा नहीं है।
माइक ग्राहम


उपयोगी अनुकूलन को कम करने के लिए python.org/doc/essays/list2str देखें । यह सामान्य रूप से सूचियों, सेटों, तारों आदि के निर्माण के लिए काफी अच्छी तरह से उपयोग किया जा सकता है। वर्थ एक नज़र भी github.com/EntilZha/PyFunctional
एंड्रियास

ध्यान दें resultकि खाली होने पर आप अपना लूप तोड़कर ऑप्टिमाइज़ कर सकते हैं ।
bfontaine

1

यहाँ मैं कई सेट चौराहों के लिए एक सामान्य कार्य की पेशकश कर रहा हूँ जो उपलब्ध सर्वोत्तम विधि का लाभ उठाने की कोशिश कर रहा है:

def multiple_set_intersection(*sets):
    """Return multiple set intersection."""
    try:
        return set.intersection(*sets)
    except TypeError: # this is Python < 2.6 or no arguments
        pass

    try: a_set= sets[0]
    except IndexError: # no arguments
        return set() # return empty set

    return reduce(a_set.intersection, sets[1:])

गुइडो को नापसंद हो सकता है reduce, लेकिन मैं इसे पसंद कर रहा हूँ :)


आपको setsएक्सेस करने sets[0]और पकड़ने की कोशिश करने के बजाय लंबाई की जांच करनी चाहिए IndexError
13 फरवरी को bfontaine

यह एक सादा जाँच नहीं है; a_setअंतिम रिटर्न में उपयोग किया जाता है।
17

क्या तुम नहीं कर सकते return reduce(sets[0], sets[1:]) if sets else set()?
bfontaine

हा हां, धन्यवाद। कोड को बदलना चाहिए क्योंकि try/ a पर भरोसा करने exceptसे बचना चाहिए यदि आप कर सकते हैं। यह एक कोड गंध है, अक्षम है, और अन्य समस्याओं को छिपा सकता है।
bfontaine

0

जीन-फ्रांकोइस फेब्रे सेट.इंटनेस (* list_of_sets) उत्तर निश्चित रूप से सबसे पाइटोनिक है और सही रूप से स्वीकृत उत्तर है।

उन लोगों के लिए जो कम उपयोग करना चाहते हैं, निम्नलिखित भी काम करेंगे:

reduce(set.intersection, list_of_sets)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.