व्यक्त करने का एक और अधिक सुंदर तरीका है ((x == a और y == b) या (x == b और y == a))?


108

मैं ((x == a and y == b) or (x == b and y == a))पायथन में मूल्यांकन करने की कोशिश कर रहा हूं , लेकिन यह थोड़ा क्रियात्मक लगता है। वहाँ एक और अधिक सुंदर तरीका है?


8
निर्भर करता है कि किस प्रकार की वस्तुएं x,y, a,bहैं: वे ints / floats / strings, मनमानी वस्तुएं, या क्या हैं? अगर वे प्रकार निर्मित थे और यह संभव हो गया था दोनों रखने के लिए x,yऔर a,bक्रमबद्ध क्रम में है, तो आप दूसरे शाखा से बच सकते हैं। ध्यान दें कि एक सेट बनाने से चार तत्वों में x,y, a,bसे प्रत्येक को हैशेड किया जाएगा, जो कि तुच्छ नहीं हो सकता है या एक प्रदर्शन निहितार्थ हो सकता है कि वे किस प्रकार की वस्तुओं पर पूरी तरह से निर्भर करते हैं।
मुस्कान

18
उन लोगों को ध्यान में रखें जिनके साथ आप काम कर रहे हैं और जिस तरह की परियोजना आप विकसित कर रहे हैं। मैं इधर-उधर थोड़ा सा पायथन इस्तेमाल करता हूं। अगर किसी ने यहाँ उत्तर में से एक को कोडित किया है तो मुझे पूरी तरह से यह जानना होगा कि क्या हो रहा है। आपका सशर्त पढ़ने योग्य है, चाहे जो भी हो।
13

3
मैं किसी भी प्रतिस्थापन से परेशान नहीं होता। वे अधिक सुरीले हैं, लेकिन स्पष्ट (IMHO) नहीं हैं और मुझे लगता है कि सभी धीमे होंगे।
बरमार

22
यह एक क्लासिक XYAB समस्या है।
ताशूस

5
और सामान्य तौर पर यदि आप ऑब्जेक्ट्स के ऑर्डर-इंडिपेंडेंट कलेक्शन के साथ काम कर रहे हैं, तो सेट / डाइक / आदि का उपयोग करें। यह वास्तव में एक XY समस्या है, हमें इससे बने बड़े कोडबेस को देखना होगा। मैं मानता हूं कि ((x == a and y == b) or (x == b and y == a))यह अजीब लग सकता है, लेकिन 1) इसका इरादा क्रिस्टल स्पष्ट है और सभी गैर-पायथन प्रोग्रामर्स के लिए समझदार है, न कि क्रिप्टिक 2) दुभाषियों / संकलक हमेशा इसे अच्छी तरह से संभाल लेंगे और यह अनिवार्य रूप से गैर-निष्पादन कोड में परिणाम नहीं कर सकता है, इसके विपरीत विकल्प। तो, 'अधिक सुरुचिपूर्ण' में गंभीर डाउनसाइड भी हो सकते हैं।
smci

जवाबों:


151

यदि तत्व उपलब्ध हैं, तो आप सेट का उपयोग कर सकते हैं:

{a, b} == {y, x}

18
@ ग्राहम नहीं, क्योंकि दाहिने हाथ के सेट में ठीक दो आइटम हैं। यदि दोनों ए हैं, तो कोई बी नहीं है, और यदि दोनों बी हैं, तो कोई भी नहीं है, और किसी भी मामले में सेट समान नहीं हो सकते हैं।
हॉब्स

12
दूसरी ओर, अगर हमारे पास प्रत्येक तरफ तीन तत्व थे और हमें यह परीक्षण करने की आवश्यकता थी कि क्या वे एक से एक तक मेल खा सकते हैं, तो सेट काम करेगा। {1, 1, 2} == {1, 2, 2}। उस बिंदु पर, आपको आवश्यकता है sortedया Counter
user2357112

11
मुझे यह पढ़ने में मुश्किल लगता है ("{}" को "()" के रूप में न पढ़ें)। यह टिप्पणी करने के लिए पर्याप्त है - और फिर उद्देश्य खो जाता है।
.douard

9
मुझे पता है कि यह अजगर है, लेकिन मूल्यों की तुलना करने के लिए दो नए सेट बनाना मेरे लिए एक ओवरकिल की तरह लगता है ... बस एक फ़ंक्शन को परिभाषित करें जो यह करता है और ज़रूरत पड़ने पर कॉल करता है।
marxin

5
@marxin एक समारोह 2 सरल सेट निर्माणों की तुलना में भी बड़ा ओवरकिल होगा। और 4 तर्कों के साथ कम पठनीय।
ग्लोवेय

60

मुझे लगता है कि आपको जो सबसे अच्छा मिल सकता है, वह उन्हें टुपल्स में पैकेज करना है:

if (a, b) == (x, y) or (a, b) == (y, x)

या, हो सकता है कि एक सेट लुकअप में लपेटें

if (a, b) in {(x, y), (y, x)}

बस जब से यह एक दो टिप्पणियों द्वारा उल्लेख किया गया था, मैंने कुछ समय किया, और लुकअप और सेट यहां दिखाई देते हैं जब लुकअप दिखाई देता है:

from timeit import timeit

x = 1
y = 2
a = 3
b = 4

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
32.8357742

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
31.6169182

हालांकि लुकअप के सफल होने पर टुपल्स वास्तव में तेज़ होते हैं:

x = 1
y = 2
a = 1
b = 2

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
35.6219458

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
27.753138700000008

मैंने एक सेट का उपयोग करने के लिए चुना क्योंकि मैं एक सदस्यता लुकअप कर रहा हूं, और वैचारिक रूप से एक सेट एक ट्यूपल की तुलना में उस उपयोग के मामले के लिए एक बेहतर फिट है। यदि आपने किसी विशेष उपयोग के मामले में दो संरचनाओं के बीच एक महत्वपूर्ण अंतर मापा है, तो तेज के साथ जाएं। मुझे नहीं लगता कि प्रदर्शन यहाँ एक कारक है।


12
टपल विधि बहुत साफ दिखती है। मैं एक सेट का उपयोग करने के प्रदर्शन प्रभाव के बारे में चिंतित हूँ। आप कर सकते हैं if (a, b) in ((x, y), (y, x)), हालांकि?
ब्रिलिएंड

18
@ ब्रिलियन यदि आप प्रदर्शन प्रभाव के बारे में चिंतित हैं, तो पायथन आपके लिए भाषा नहीं है। :
स्नेफेल

मैं वास्तव में पहली विधि, दो टपल तुलना पसंद करता हूं। यह पार्स करना आसान है (एक समय में एक खंड) और प्रत्येक खंड बहुत सरल है। और ऊपर से, यह अपेक्षाकृत कुशल होना चाहिए।
मैथ्यू एम।

set@ ब्रिलियनड से टपल समाधान के उत्तर में समाधान पसंद करने का कोई कारण है ?
user1717828

एक सेट के लिए यह आवश्यक है कि वस्तुएं होंश में हों, इसलिए कम निर्भरता के साथ एक सामान्य समाधान होगा। प्रदर्शन, जबकि आम तौर पर महत्वपूर्ण नहीं होता है, महंगी हैशिंग और समानता की जांच के साथ बड़ी वस्तुओं के साथ काम करते समय भी बहुत अलग दिख सकता है।
Dukeling

31

Tuples इसे थोड़ा और पठनीय बनाते हैं:

(x, y) == (a, b) or (x, y) == (b, a)

यह एक सुराग देता है: हम जाँच रहे हैं कि क्या अनुक्रम अनुक्रम x, yके बराबर है a, bलेकिन आदेश की अनदेखी कर रहा है। यह सिर्फ समानता है!

{x, y} == {a, b}

,एक सूची बनाता है, एक सूची नहीं। इसलिए (x, y)और (a, b)टुपल्स हैं, जैसे कि x, yऔर a, b
kissgyorgy

मेरा मतलब "सूची" "तत्वों के क्रमबद्ध" के अर्थ में था, पायथन listप्रकार के अर्थ में नहीं । संपादित क्योंकि वास्तव में यह भ्रामक था।
थॉमस

27

यदि आइटम उपलब्ध नहीं हैं, लेकिन तुलना का आदेश देने का समर्थन करते हैं, तो आप कोशिश कर सकते हैं:

sorted((x, y)) == sorted((a, b))

चूंकि यह हैशटैग आइटम्स के साथ-साथ (दाएं?) काम करता है, इसलिए यह अधिक वैश्विक समाधान है।
कार्ल विटथॉफ्ट

5
@CarlWitthoft: नहीं। ऐसे प्रकार हैं जो धोने योग्य हैं, लेकिन क्रमबद्ध नहीं हैं: complexउदाहरण के लिए।
dan04

26

मेरी राय में, सबसे सुंदर तरीका होगा

(x, y) in ((a, b), (b, a))

यह सेट का उपयोग करने से बेहतर तरीका है, अर्थात {a, b} == {y, x}, जैसा कि अन्य उत्तरों में संकेत दिया गया है क्योंकि हमें यह सोचने की आवश्यकता नहीं है कि चर चर हैं या नहीं।


यह पहले के उत्तर से कैसे भिन्न होता है ?
scohe001

5
@ scohe001 यह एक टपल का उपयोग करता है जहां पहले वाला उत्तर सेट का उपयोग करता है। उस पहले के उत्तर ने इस समाधान पर विचार किया था, लेकिन इसे सिफारिश के रूप में सूचीबद्ध करने से इनकार कर दिया।
ब्रिलियनड

25

यदि ये नंबर हैं, तो आप उपयोग कर सकते हैं (x+y)==(a+b) and (x*y)==(a*b)

यदि ये तुलनीय आइटम हैं, तो आप उपयोग कर सकते हैं min(x,y)==min(a,b) and max(x,y)==max(a,b)

लेकिन ((x == a and y == b) or (x == b and y == a))स्पष्ट, सुरक्षित और अधिक सामान्य है।


2
हाहा, सममित बहुपद फली!
कार्स्टन एस

2
मुझे लगता है कि यह अतिप्रवाह त्रुटियों का खतरा पैदा करता है।
रज़वान सोकोल

3
यह सही उत्तर है, विशेष रूप से अंतिम वाक्य। इसे सरल रखें, इसके लिए कई नए पुनरावृत्तियों या कुछ भी ऐसा करने की आवश्यकता नहीं होनी चाहिए। उन लोगों के लिए जो सेट का उपयोग करना चाहते हैं, सेट ऑब्जेक्ट्स के कार्यान्वयन पर एक नज़र डालें और फिर एक तंग पाश में इसे चलाने की कोशिश करने की कल्पना करें ...
Z4-tier

3
@RazvanSocol OP ने यह नहीं बताया कि डेटा प्रकार क्या हैं, और यह उत्तर उन समाधानों को योग्य बनाता है जो टाइप-निर्भर हैं।
Z4-tier

21

दो से अधिक चरों के सामान्यीकरण के रूप में हम इसका उपयोग कर सकते हैं itertools.permutations। इसके बजाय है

(x == a and y == b and z == c) or (x == a and y == c and z == b) or ...

हम लिख सकते है

(x, y, z) in itertools.permutations([a, b, c])

और निश्चित रूप से दो चर संस्करण:

(x, y) in itertools.permutations([a, b])

5
बहुत बढ़िया जवाब। यह यहाँ इंगित करने के लायक है (उन लोगों के लिए, जिन्होंने पहले जनरेटर के साथ बहुत कुछ नहीं किया है) यह बहुत ही स्मृति कुशल है, क्योंकि एक समय में केवल एक ही क्रमपरिवर्तन बनाया जाता है, और "इन" चेक बंद हो जाएगा और तुरंत बाद वापस आ जाएगा। मैच मिला है।
रॉबर्टबटन

2
यह भी इंगित करने योग्य है कि इस पद्धति की जटिलता क्या है O(N*N!); 11 चर के लिए, यह खत्म होने में एक सेकंड का समय ले सकता है। (मैंने एक तेज़ तरीका पोस्ट किया है, लेकिन यह अभी भी लेता है O(N^2), और 10k चर पर एक दूसरे से अधिक लेना शुरू कर देता है; इसलिए ऐसा लगता है कि यह या तो तेजी से या आम तौर पर किया जा सकता है (wrt हैशबिलिटी / ऑर्डरबिलिटी), लेकिन दोनों नहीं: P)
एलेक्सा टोरमो।

15

आप अपने डेटा का प्रतिनिधित्व करने के लिए ट्यूपल्स का उपयोग कर सकते हैं और फिर सेट अपवर्जन के लिए जांच कर सकते हैं, जैसे:

def test_fun(x, y):
    test_set = {(a, b), (b, a)}

    return (x, y) in test_set

3
एक-लाइनर के रूप में और एक सूची के साथ (गैर-धोने योग्य वस्तुओं के लिए) लिखा, मैं इसे सबसे अच्छा जवाब मानूंगा। (हालांकि मैं एक पूर्ण पायथन नौसिखिया हूं)।
.douard

1
@ Thatdouard अब एक और जवाब है जो अनिवार्य रूप से है (बस एक सूची के बजाय एक टपल के साथ, जो वैसे भी अधिक कुशल है)।
ब्रिलियनड

10

आपको पहले से ही सबसे पठनीय हल मिल गया । इसे व्यक्त करने के अन्य तरीके हैं, शायद कम पात्रों के साथ, लेकिन वे पढ़ने के लिए कम-सीधे हैं।

इस बात पर निर्भर करता है कि वास्तव में आपका सबसे अच्छा दांव क्या दर्शाता है , चेक को बोलने वाले नाम के साथ लपेटना है । वैकल्पिक रूप से या इसके अलावा, आप वस्तुओं को x, y और a, b को समर्पित उच्च श्रेणी की वस्तुओं में से प्रत्येक में मॉडल कर सकते हैं जो आप तब वर्ग समानता जांच विधि या एक समर्पित कस्टम फ़ंक्शन में तुलना के तर्क के साथ तुलना कर सकते हैं।


3

ऐसा लगता है कि ओपी केवल दो चर के मामले से संबंधित था, लेकिन चूंकि स्टैकऑवरफ्लो उन लोगों के लिए भी है जो बाद में एक ही प्रश्न की खोज करते हैं, इसलिए मैं यहां कुछ विस्तार से सामान्य मामले से निपटने की कोशिश करूंगा; एक पिछले उत्तर में पहले से ही एक जेनेरिक उत्तर का उपयोग किया गया है itertools.permutations(), लेकिन यह विधि O(N*N!)तुलना की ओर ले जाती है , क्योंकि प्रत्येक आइटम के N!साथ क्रमपरिवर्तन Nहोते हैं। (इस उत्तर के लिए यह मुख्य प्रेरणा थी)

पहले, आइए संक्षेप में बताएं कि पिछले उत्तरों में से कुछ तरीके जेनेरिक मामले पर कैसे लागू होते हैं, क्योंकि यहां प्रस्तुत विधि के लिए प्रेरणा है। मैं का उपयोग किया जाएगा Aउल्लेख करने के लिए (x, y)और Bका उल्लेख करने (a, b), मनमाने ढंग से (लेकिन समान) लंबाई की tuples हो सकता है।

set(A) == set(B)तेजी से होता है, लेकिन केवल तभी काम करता है यदि मान उपलब्ध नहीं होते हैं और आप यह गारंटी दे सकते हैं कि ट्यूपल्स में से कोई भी डुप्लिकेट मान नहीं रखता है। (जैसे। {1, 1, 2} == {1, 2, 2}@Daniel Mesejo के जवाब के तहत @ user2357112 द्वारा बताया गया)

पिछली पद्धति को डुप्लिकेट मानों के साथ काम करने के लिए सेट के बजाय, के साथ शब्दकोशों का उपयोग करके बढ़ाया जा सकता है: (यह अभी भी सीमा है कि सभी मूल्यों को धोने योग्य होने की आवश्यकता है, इसलिए जैसे। परिवर्तनशील मान listकाम नहीं करेंगे)

def counts(items):
    d = {}
    for item in items:
        d[item] = d.get(item, 0) + 1
    return d

counts(A) == counts(B)

sorted(A) == sorted(B)धोने योग्य मूल्यों की आवश्यकता नहीं है, लेकिन थोड़ा धीमा है, और इसके बजाय क्रमबद्ध मूल्यों की आवश्यकता है। (इसलिए जैसे complexकाम नहीं करेगा)

A in itertools.permutations(B)हैशेबल या ऑर्डर करने योग्य मूल्यों की आवश्यकता नहीं होती है, लेकिन जैसा कि पहले ही उल्लेख किया गया है, इसमें O(N*N!)जटिलता है, इसलिए केवल 11 वस्तुओं के साथ, इसे खत्म होने में एक सेकंड लग सकता है।

तो, क्या सामान्य होने का एक तरीका है, लेकिन क्या यह काफी तेज है? क्यों हाँ, "मैन्युअल रूप से" जाँच करके कि प्रत्येक आइटम की समान मात्रा है: (इस एक की जटिलता है O(N^2), इसलिए यह बड़े इनपुट के लिए अच्छा नहीं है; मेरी मशीन पर, 10k आइटम एक सेकंड से अधिक ले सकते हैं - लेकिन साथ छोटे इनपुट, जैसे 10 आइटम, यह दूसरों की तरह ही तेज है)

def unordered_eq(A, B):
    for a in A:
        if A.count(a) != B.count(a):
            return False
    return True

सर्वश्रेष्ठ प्रदर्शन प्राप्त करने के लिए, कोई व्यक्ति dictपहले sortedसे संचालित पद्धति को आजमाना चाहता है, -बेड विधि पर वापस आ सकता है, यदि वह मानों के कारण विफल हो जाती है, और अंत में -बेड countविधि में वापस गिर जाती है, यदि वह भी असंगत मूल्यों के कारण विफल हो जाती है।

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