अजगर: कुछ शर्तों के साथ सूची (अनुक्रम) से आइटम प्राप्त करें


84

यह मानते हुए कि मेरे पास बड़ी संख्या में वस्तुओं के साथ एक सूची है।

l = [ 1, 4, 6, 30, 2, ... ]

मैं उस सूची से आइटम की संख्या प्राप्त करना चाहता हूं, जहां एक आइटम को कुछ शर्त को पूरा करना चाहिए। मेरा पहला विचार था:

count = len([i for i in l if my_condition(l)])

लेकिन अगर my_condition () फ़िल्टर की गई सूची में भी बड़ी संख्या में आइटम हैं, तो मुझे लगता है कि फ़िल्टर किए गए परिणाम के लिए नई सूची बनाना सिर्फ स्मृति की बर्बादी है। दक्षता के लिए, IMHO, उपरोक्त कॉल इससे बेहतर नहीं हो सकती:

count = 0
for i in l:
    if my_condition(l):
        count += 1

क्या अस्थायी सूची तैयार किए बिना कुछ शर्त को पूरा करने वाली वस्तुओं को # प्राप्त करने के लिए कोई कार्यात्मक शैली है?

अग्रिम में धन्यवाद।


3
जनरेटर और सूचियों के बीच चयन निष्पादन समय और स्मृति खपत के बीच एक विकल्प है। यदि आप कोड को प्रोफाइल करते हैं तो आप आश्चर्यचकित होंगे कि परिणाम कितनी बार काउंटर सहज हैं। सभी बुराईयो की जड़ समयपूर्व इष्टतमीकरण है।
पाउलो स्कार्डिन

जवाबों:


102

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

>>> l = [1, 3, 7, 2, 6, 8, 10]
>>> sum(1 for i in l if i % 4 == 3)
2

या और भी

>>> sum(i % 4 == 3 for i in l)
2

जो इस तथ्य का उपयोग करता है int(True) == 1

वैकल्पिक रूप से, आप उपयोग कर सकते हैं itertools.imap(अजगर 2) या बस map(अजगर 3):

>>> def my_condition(x):
...     return x % 4 == 3
... 
>>> sum(map(my_condition, l))
2

1
@mgilson: मुझे नहीं लगता कि यह कभी भी गणना करता है - start0 से चूक, इसलिए पहला जोड़ है True + 0, नहीं?
DSM

4
हाँ। शायद मुझे अधिक स्पष्ट होना चाहिए ... इससे कोई फर्क नहीं पड़ता कि क्या int(True)है। int("1") == 1भी, लेकिन इसका मतलब यह नहीं है कि आप कर सकते हैं "1" + 0। क्या मायने रखता है कि अजगर कैसे मूल्यांकन करता है integer + Trueया integer + False
एमजीसिलसन

2
@mgilson: हम्म, ठीक है, आपने मुझे आश्वस्त किया है।
DSM

4
मुद्दा यह है कि boolआप एक उपवर्ग हैं intऔर आप आसानी से बूल और इनट्स जोड़ सकते हैं ( True1 के मान के साथ और False0 के मान के साथ)।
1

ठीक है, यह वही है जो मैं उल्लेख करके प्राप्त कर रहा था int(True) == 1, लेकिन आपकी बात जो इस बात को int("1") == 1प्रमाणित करती है कि इस तरह से यह उन चीजों का संकेत दे सकता है जो सच नहीं हैं।
DSM

21

आप यहां एक सूची के बजाय एक जनरेटर समझ चाहते हैं।

उदाहरण के लिए,

l = [1, 4, 6, 7, 30, 2]

def my_condition(x):
    return x > 5 and x < 20

print sum(1 for x in l if my_condition(x))
# -> 2
print sum(1 for x in range(1000000) if my_condition(x))
# -> 14

या उपयोग itertools.imap(हालांकि मुझे लगता है कि स्पष्ट सूची और जनरेटर के भाव कुछ अधिक पाइथोनिक लगते हैं)।

ध्यान दें कि, हालांकि यह sumउदाहरण से स्पष्ट नहीं है , आप जनरेटर की समझ को अच्छी तरह से बना सकते हैं। उदाहरण के लिए,

inputs = xrange(1000000)      # In Python 3 and above, use range instead of xrange
odds = (x for x in inputs if x % 2)  # Pick odd numbers
sq_inc = (x**2 + 1 for x in odds)    # Square and add one
print sum(x/2 for x in sq_inc)       # Actually evaluate each one
# -> 83333333333500000

इस तकनीक के बारे में अच्छी बात यह है कि जब तक अंतिम परिणाम का मूल्यांकन नहीं किया जाता तब तक आप मूल्यांकन और मेमोरी में स्टोरेज के बिना कोड में वैचारिक रूप से अलग-अलग चरणों को निर्दिष्ट कर सकते हैं।


10

reduceयदि आप कार्यात्मक प्रोग्रामिंग पसंद करते हैं तो इसका उपयोग भी किया जा सकता है

reduce(lambda count, i: count + my_condition(i), l, 0)

इस तरह से आप केवल 1 पास करते हैं और कोई मध्यवर्ती सूची उत्पन्न नहीं होती है।


7

आप कुछ ऐसा कर सकते हैं:

l = [1,2,3,4,5,..]
count = sum(1 for i in l if my_condition(i))

जो सिर्फ प्रत्येक तत्व के लिए 1 जोड़ता है जो स्थिति को संतुष्ट करता है।


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