लूप और IF स्टेटमेंट को मिलाने का पाइथोनिक तरीका


266

मुझे पता है कि दोनों छोरों का उपयोग कैसे करना है और यदि अलग-अलग लाइनों पर बयान करना है, जैसे:

>>> a = [2,3,4,5,6,7,8,9,0]
... xyz = [0,12,4,6,242,7,9]
... for x in xyz:
...     if x in a:
...         print(x)
0,4,6,7,9

और मुझे पता है कि मैं बयानों को सरल बनाने के लिए सूची संयोजन का उपयोग कर सकता हूं, जैसे कि:

print([x for x in xyz if x in a])

लेकिन जो मुझे नहीं मिल रहा है, वह एक अच्छा उदाहरण कहीं भी है (कॉपी और सीखने के लिए) कमांड के एक जटिल सेट का प्रदर्शन करना (न कि केवल "प्रिंट एक्स") जो लूप के लिए और कुछ स्टेटमेंट्स के संयोजन के बाद होता है। कुछ ऐसा है जिसकी मुझे अपेक्षा है:

for x in xyz if x not in a:
    print(x...)

क्या यह सिर्फ अजगर के काम करने का तरीका नहीं है?


23
यह है कि यह कैसे है ... उन्हें सरल बनाने की कोशिश करके चीजों को अधूरा मत करो। पाइथोनिक का मतलब हर स्पष्ट forलूप और ifबयान से बचना नहीं है ।
फेलिक्स क्लिंग

2
आप लूप के लिए अपनी सूची की समझ में उत्पन्न सूची का उपयोग कर सकते हैं। यह कुछ हद तक आपके अंतिम उदाहरण जैसा लगेगा।
जैकब

तो प्रसंस्करण के लिए नीचे हो रहा है, अगर एक बयान के साथ लूप के लिए संयोजन करने का सबसे तेज़ तरीका क्या है, अगर बयान में उन मूल्यों को शामिल किया गया है जो पहले से मेल खा चुके हैं और सूची लूप के पुनरावृत्ति के दौरान लगातार बढ़ रही है?
12 अक्टूबर को ChewyChunks

3
@ काई, उचित डेटा संरचनाएं कोड को तेज कर देंगी, न कि संश्लिष्ट चीनी। उदाहरण के लिए, x in aयदि aसूची है तो धीमा है।
निक डंडौलकिस

1
यह पायथन, एक व्याख्या की गई भाषा है; किसी की चर्चा क्यों है कि कोड कितना तेज़ है?
19O को ArtOfWarfare

जवाबों:


323

आप इस तरह जनरेटर भाव का उपयोग कर सकते हैं :

gen = (x for x in xyz if x not in a)

for x in gen:
    print x

1
gen = (y for (x,y) in enumerate(xyz) if x not in a)रिटर्न >>> 12जब मैं टाइप करता हूं for x in gen: print x- तो एन्युमरेट के साथ अप्रत्याशित व्यवहार क्यों?
ChewyChunks

9
संभव है, लेकिन अगर ब्लॉक के लिए मूल की तुलना में अच्छा नहीं है।
माइक ग्राहम

1
@ChewyChunks। यह काम करेगा लेकिन गणना करने का आह्वान बेमानी है।
Johnsyweb

132
मैं वास्तव में अजगर को यह कहने में सक्षम हूंfor x in xyz if x:
bgusach

10
for x in (x for x in xyz if x not in a):मेरे लिए काम करता है, लेकिन आप सिर्फ करने में सक्षम क्यों नहीं होना चाहिए for x in xyz if x not in a:, मुझे यकीन नहीं है ...
मैट वेनहम

34

पायथन के ज़ेन के अनुसार (यदि आप सोच रहे हैं कि क्या आपका कोड "पायथन" है, तो जाने का स्थान है):

  • सुंदर बदसूरत से बेहतर है।
  • निहितार्थ की तुलना में स्पष्ट है।
  • सरल जटिल से बेहतर है।
  • फ्लैट नेस्टेड से बेहतर है।
  • पठनीयता मायने रखती है।

दो एस पाने का पायथोनिक तरीका है:sorted intersectionset

>>> sorted(set(a).intersection(xyz))
[0, 4, 6, 7, 9]

या वे तत्व जो xyzइसमें नहीं हैं a:

>>> sorted(set(xyz).difference(a))
[12, 242]

लेकिन अधिक जटिल लूप के लिए आप एक अच्छी तरह से नामित जनरेटर अभिव्यक्ति और / या एक अच्छी तरह से नामित फ़ंक्शन को कॉल करके इसे समतल करना चाहते हैं । एक पंक्ति में सब कुछ फिट करने की कोशिश करना शायद ही कभी "पायथोनिक" है।


अपने प्रश्न और स्वीकृत उत्तर पर अतिरिक्त टिप्पणियों के बाद अपडेट करें

मुझे यकीन नहीं है कि आप क्या करने की कोशिश कर रहे हैं enumerate, लेकिन अगर aएक शब्दकोश है, तो आप शायद इस तरह से कुंजियों का उपयोग करना चाहते हैं:

>>> a = {
...     2: 'Turtle Doves',
...     3: 'French Hens',
...     4: 'Colly Birds',
...     5: 'Gold Rings',
...     6: 'Geese-a-Laying',
...     7: 'Swans-a-Swimming',
...     8: 'Maids-a-Milking',
...     9: 'Ladies Dancing',
...     0: 'Camel Books',
... }
>>>
>>> xyz = [0, 12, 4, 6, 242, 7, 9]
>>>
>>> known_things = sorted(set(a.iterkeys()).intersection(xyz))
>>> unknown_things = sorted(set(xyz).difference(a.iterkeys()))
>>>
>>> for thing in known_things:
...     print 'I know about', a[thing]
...
I know about Camel Books
I know about Colly Birds
I know about Geese-a-Laying
I know about Swans-a-Swimming
I know about Ladies Dancing
>>> print '...but...'
...but...
>>>
>>> for thing in unknown_things:
...     print "I don't know what happened on the {0}th day of Christmas".format(thing)
...
I don't know what happened on the 12th day of Christmas
I don't know what happened on the 242th day of Christmas

नीचे दिए गए टिप्पणियों से लगता है, मुझे जनरेटर पर अध्ययन करना चाहिए। मैंने उनका कभी उपयोग नहीं किया है। धन्यवाद। क्या जेनरेटर फॉर और आईएफ के समान संयोजन से तेज है? मैंने भी सेट का उपयोग किया है, लेकिन कभी-कभी सूची में अनावश्यक तत्व ऐसी जानकारी होते हैं जिन्हें मैं त्याग नहीं सकता।
ChewyChunks

@ChewyChunks: जेनरेटर पाइथोनिक होने का एकमात्र तरीका नहीं है!
जॉन्सवेब

3
@ जॉनोवेब, यदि आप पायथन के ज़ेन को उद्धृत करने जा रहे हैं: "एक होना चाहिए - और अधिमानतः इसे करने के लिए केवल एक ही - स्पष्ट तरीका।"
Wooble

@Ooble: वहाँ होना चाहिए। मैंने उस अनुभाग को उसी समय के आसपास एक अन्य प्रश्न के उत्तर में उद्धृत किया !
Johnsyweb

18

मुझे व्यक्तिगत रूप से लगता है कि यह सबसे सुंदर संस्करण है:

a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]
for x in filter(lambda w: w in a, xyz):
  print x

संपादित करें

यदि आप लैम्बडा का उपयोग करने से बचने के लिए बहुत उत्सुक हैं तो आप आंशिक फ़ंक्शन अनुप्रयोग का उपयोग कर सकते हैं और ऑपरेटर मॉड्यूल का उपयोग कर सकते हैं (जो कि अधिकांश ऑपरेटरों के कार्यों को प्रदान करता है)।

https://docs.python.org/2/library/operator.html#module-operator

from operator import contains
from functools import partial
print(list(filter(partial(contains, a), xyz)))

4
filter(a.__contains__, xyz)। आमतौर पर जब लोग लैम्ब्डा का उपयोग करते हैं, तो उन्हें वास्तव में बहुत सरल चीज़ की आवश्यकता होती है।
वेकी जूल 18'15

मुझे लगता है कि आपने कुछ गलत समझा। __contains__किसी भी अन्य की तरह एक विधि है, केवल यह एक विशेष विधि है, जिसका अर्थ है कि इसे अप्रत्यक्ष रूप से एक ऑपरेटर ( inइस मामले में) कहा जा सकता है । लेकिन इसे सीधे भी कहा जा सकता है, यह सार्वजनिक एपीआई का एक हिस्सा है। निजी नामों को विशेष रूप से अधिकतम एक अनुगामी अंडरस्कोर में होने के रूप में परिभाषित किया जाता है, विशेष विधि के नाम के लिए अपवाद प्रदान करने के लिए - और वे जब वर्ग स्कोप में शाब्दिक नाम के अधीन होते हैं। Docs.python.org/3/reference/datamodel.html#specialnames और docs.python.org/3.6/tutorial/classes.html#private-variables देखें ।
Veky

यह निश्चित रूप से ठीक है, लेकिन सिर्फ एक विशेषता का उपयोग करने के लिए सुलभ एक विधि को संदर्भित करने में सक्षम होने के लिए दो आयात अजीब लगते हैं (ऑपरेटरों को आमतौर पर तब उपयोग किया जाता है जब डबल प्रेषण आवश्यक होता है, लेकिन inअकेले प्रेषण राइट ऑपरेंड भेजा जाता है)। इसके अलावा, ध्यान दें कि नाम के तहत विधि operatorभी निर्यात containsकरती है __contains__, इसलिए यह निश्चित रूप से एक निजी नाम नहीं है। मुझे लगता है कि आपको इस तथ्य के साथ जीना सीखना होगा कि हर डबल अंडरस्कोर का मतलब "दूर रखना" नहीं है। : -]
Veky

मुझे लगता है कि आपकी lambdaआवश्यकताओं को शामिल करना तय है not: lambda w: not w in a, xyz
javadba

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

16

निम्नांकित उत्तर में से एक सरलीकरण / एक लाइनर है:

a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]

for x in (x for x in xyz if x not in a):
    print(x)

12
242

ध्यान दें कि इनलाइनgenerator रखी गई थी । इस पर परीक्षण किया गया था और (नोटिस parens in ;))python2.7python3.6print


10

मैं शायद उपयोग करूंगा:

for x in xyz: 
    if x not in a:
        print x...

@KirillTitov हाँ अजगर एक मौलिक रूप से गैर-कार्यात्मक भाषा है (यह एक विशुद्ध रूप से अनिवार्य कोडिंग है - और मैं इस उत्तर के लेखक से सहमत हूं कि यह जिस तरह से अजगर को लिखा जाना है। कार्यात्मक का उपयोग करने का प्रयास करने से खराब पढ़ने या गैर-पढ़ने की ओर जाता है। pythonicपरिणाम मैं हर दूसरे भाषा मैं उपयोग में कार्यात्मक कोड कर सकते हैं (स्केला, kotlin, जावास्क्रिप्ट, आर, स्विफ्ट, ..) लेकिन मुश्किल / में अजगर अजीब।
javadba

9
a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]  
set(a) & set(xyz)  
set([0, 9, 4, 6, 7])

बहुत ज़ेन, @ इलाज़ेर, लेकिन मुझे एक जटिल कोड ब्लॉक को बेहतर बनाने में मदद नहीं करेगा जो एक सूची के माध्यम से पुनरावृत्ति करने और किसी अन्य सूची में मिलान तत्वों की अनदेखी करने पर निर्भर करता है। क्या पहली सूची को एक सेट के रूप में मानना ​​और एक दूसरे के साथ संघ / अंतर की तुलना करना तेजी से बढ़ रहा है, "अनदेखी" सूची?
ChewyChunks

इसके लिए प्रयास करेंimport time a = [2,3,4,5,6,7,8,9,0] xyz = [0,12,4,6,242,7,9] start = time.time() print (set(a) & set(xyz)) print time.time() - start
Kracekumar

@ChewyChunks यदि या तो सूचियों में परिवर्तन के दौरान यह संभवतया अनदेखा सूची के विरुद्ध प्रत्येक तत्व की जाँच करने के लिए तेज़ होगा - सिवाय इसके कि आपको इसे अनदेखा करना चाहिए। सेटों में सदस्यता के लिए जाँच बहुत तेज़ है if x in ignore: ...:।
लॉरिट्ज वी। थुलोव

@lazyr मैं सिर्फ एक अनदेखा सूची पर सेट एक उपेक्षा का उपयोग कर अपने कोड को फिर से लिखा है । समय को बहुत धीमा करने की अपील करता है। (निष्पक्ष होना मैं तुलना करने की तुलना कर रहा था if set(a) - set(ignore) == set([]):शायद इसलिए सदस्यता की जाँच करने की तुलना में यह बहुत धीमा था। मैं भविष्य में इसे फिर से बहुत सरल उदाहरण पर परीक्षण करूँगा कि मैं क्या लिख ​​रहा हूं।
ChewyChunks

5

आप जनरेटर का भी उपयोग कर सकते हैं , यदि जनरेटर के भाव बहुत अधिक जटिल या जटिल हो जाते हैं:

def gen():
    for x in xyz:
        if x in a:
            yield x

for x in gen():
    print x

यह मेरे लिए थोड़ा अधिक उपयोगी है। मैंने कभी जनरेटर नहीं देखा। वे डरावने लगते हैं (क्योंकि मैंने उन्हें उन मॉड्यूलों में देखा था जो आमतौर पर उपयोग करने के लिए एक दर्द थे)।
ChewyChunks

2

का उपयोग करें intersectionयाintersection_update

  • चौराहा :

    a = [2,3,4,5,6,7,8,9,0]
    xyz = [0,12,4,6,242,7,9]
    ans = sorted(set(a).intersection(set(xyz)))
  • चौराहा_अपडेट :

    a = [2,3,4,5,6,7,8,9,0]
    xyz = [0,12,4,6,242,7,9]
    b = set(a)
    b.intersection_update(xyz)

    फिर bआपका जवाब है


2

मुझे एलेक्स का जवाब पसंद आया , क्योंकि एक फ़िल्टर बिलकुल सही है यदि किसी सूची में लागू किया गया है, तो यदि आप किसी शर्त को दिए गए सूची के सबसेट का पता लगाना चाहते हैं, तो यह सबसे स्वाभाविक तरीका है

mylist = [1,2,3,4,5]
another_list = [2,3,4]

wanted = lambda x:x in another_list

for x in filter(wanted, mylist):
    print(x)

यह विधि चिंताओं के पृथक्करण के लिए उपयोगी है, यदि स्थिति में परिवर्तन होता है, तो केवल कोड के साथ फ़ेडल करना फ़ंक्शन है

mylist = [1,2,3,4,5]

wanted = lambda x:(x**0.5) > 10**0.3

for x in filter(wanted, mylist):
    print(x)

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

mylist = [1,2,3,4,5]

wanted = lambda x:(x**0.5) > 10**0.3

generator = (x**0.5 for x in mylist if wanted(x))

for x in generator:
    print(x)

इसके अलावा, फिल्टर जनरेटर के साथ काम करते हैं, हालांकि इस मामले में यह कुशल नहीं है

mylist = [1,2,3,4,5]

wanted = lambda x:(x**0.5) > 10**0.3

generator = (x**0.9 for x in mylist)

for x in filter(wanted, generator):
    print(x)

लेकिन निश्चित रूप से, इस तरह से लिखना अच्छा होगा:

mylist = [1,2,3,4,5]

wanted = lambda x:(x**0.5) > 10**0.3

# for x in filter(wanted, mylist):
for x in mylist if wanted(x):
    print(x)

0

सूचियों और बी के अद्वितीय सामान्य तत्वों को खोजने का एक सरल तरीका:

a = [1,2,3]
b = [3,6,2]
for both in set(a) & set(b):
    print(both)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.