पायथन 3 में फ़िल्टर, मैप और कम का उपयोग कैसे करें


321

filter, mapऔर reducePython 2 में पूरी तरह से काम करते हैं। यहाँ एक उदाहरण है:

>>> def f(x):
        return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]

>>> def cube(x):
        return x*x*x
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

>>> def add(x,y):
        return x+y
>>> reduce(add, range(1, 11))
55

लेकिन पायथन 3 में, मुझे निम्नलिखित आउटपुट मिलते हैं:

>>> filter(f, range(2, 25))
<filter object at 0x0000000002C14908>

>>> map(cube, range(1, 11))
<map object at 0x0000000002C82B70>

>>> reduce(add, range(1, 11))
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    reduce(add, range(1, 11))
NameError: name 'reduce' is not defined

मैं सराहना करूंगा अगर कोई मुझे समझा सकता है कि यह क्यों है।

आगे स्पष्टता के लिए कोड का स्क्रीनशॉट:

पायथन 2 और 3 के साथ-साथ साइड के आईडीएलई सत्र


1
संक्षेप में, सूची केवल डेटाटाइप नहीं है। यदि आप एक सूची चाहते हैं, तो आप एक सूची चाहते हैं। लेकिन ज्यादातर मामलों में, आप वैसे भी कुछ और चाहते हैं।
वेंकी

जवाबों:


346

आप व्हाट्स न्यू इन पायथन 3.0 में बदलावों के बारे में पढ़ सकते हैं । जब आप 2.x से 3.x पर जाते हैं तो आपको इसे अच्छी तरह से पढ़ना चाहिए क्योंकि बहुत कुछ बदल गया है।

यहाँ पूरे उत्तर प्रलेखन से उद्धरण हैं।

सूची के बजाय दृश्य और Iterators

कुछ प्रसिद्ध एपीआई अब सूची नहीं लौटाते हैं:

  • [...]
  • map()और filter()पुनरावृत्तियाँ लौटाएँ। यदि आपको वास्तव में एक सूची की आवश्यकता है, तो एक त्वरित समाधान उदा। उदाहरण के लिए list(map(...)), लेकिन एक बेहतर निर्धारण अक्सर एक सूची समझ का उपयोग करने के लिए होता है (विशेषकर जब मूल कोड लैम्ब्डा का उपयोग करता है), या कोड को फिर से लिखना ताकि उसे सूची की आवश्यकता न हो। विशेष रूप से मुश्किल map()फ़ंक्शन के साइड इफेक्ट के लिए आमंत्रित किया गया है; सही परिवर्तन एक नियमित forलूप का उपयोग करना है (क्योंकि एक सूची बनाना सिर्फ बेकार होगा)।
  • [...]

Builtins

  • [...]
  • निकाला हुआ reduce()। उपयोग करें functools.reduce()यदि आपको वास्तव में इसकी आवश्यकता है; हालांकि, 99 प्रतिशत समय एक स्पष्ट forलूप अधिक पठनीय है।
  • [...]

21
list(map(...) हर जगह जोड़ना .. दुनिया में यह है कि पठनीयता की मदद करना .. pythonकार्यात्मक कंबाइनटर के प्रगतिशील / स्ट्रीमिंग एप्लिकेशन को संभालना प्रतीत नहीं हो सकता है। अन्य भाषाओं में मैं एक संग्रह में एक दर्जन से अधिक कामों को श्रृंखलाबद्ध कर सकता हूं और यह पठनीय है। यहाँ? तुम क्या चाहते हो - एक दर्जन रास्ता नेस्टेड in??
जवदाबा

11
यदि आप एक अनिवार्य संदर्भ में काम कर रहे हैं, तो एक फॉर-लूप शायद अधिक पठनीय विकल्प है। लेकिन एक कार्यात्मक संदर्भ को पसंद करने के लिए अच्छे कारण हैं - और इससे टूट कर वापस प्रक्रियात्मक रूप में जाने के लिए बहुत ही सुंदर रूप से बदसूरत हो सकता है।
MatrixManAtYrService

2
@javadba क्या आप "स्ट्रीमिंग एप्लिकेशन" में सुनिश्चित हैं कि आपको listकॉल को जोड़ना होगा ? मुझे लगा कि "स्ट्रीमिंग" का अर्थ "कोई सूची नहीं बनाई गई है; इनपुट के प्रत्येक तत्व को अगले पर जाने से पहले पूरी तरह से संसाधित करें"।
शाही रात

@MatrixManAtYrService यदि आप सुनिश्चित हैं कि अजगर 2 व्यवहार वह है जो आपको चाहिए, तो आप हमेशा केवल पुनर्परिभाषित कर सकते हैं map
शाही रात

6
मैं अभी भी समझ नहीं पा रहा हूं कि पठनीयता का तर्क इस तरह के बदलाव की ओर कैसे ले जाता है। अगर यह प्रदर्शन के कारणों से होता तो मैं समझ सकता था ...
मिनाटो

86

की कार्यक्षमता mapऔर filterजानबूझकर iterators वापस जाने के लिए बदल गया था, और कम होने से हटा दिया गया था एक अंतर्निहित और में रखा functools.reduce

तो, के लिए filterऔर map, आप उन list()परिणामों को देखने के लिए उनके साथ लपेट सकते हैं जैसे आपने पहले किए थे।

>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> list(filter(f, range(2, 25)))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> list(map(cube, range(1, 11)))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> import functools
>>> def add(x,y): return x+y
...
>>> functools.reduce(add, range(1, 11))
55
>>>

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

>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> [i for i in range(2, 25) if f(i)]
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> [cube(i) for i in range(1, 11)]
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>>

वे कहते हैं कि छोरों के लिए 99 प्रतिशत समय कम करने की तुलना में पढ़ने में आसान है, लेकिन मैं सिर्फ इसके साथ रहना चाहता हूं functools.reduce

संपादित करें : Guido van Rossum द्वारा लिखित व्हाट्स न्यू इन पायथन 3.0 पेज से सीधे 99 प्रतिशत का आंकड़ा खींचा गया है।


5
आपको सूची बोध में अतिरिक्त कार्य करने की आवश्यकता नहीं है। बस का उपयोग करें[i*i*i for i in range(1,11)]
जिओ

2
आप बिल्कुल सही हैं। मैंने फंक्शन को लिस्ट कॉम्प्रिहेंशन उदाहरणों में रखा, ताकि इसे फिल्टर / मैप के उदाहरणों के समान रखा जा सके।
जोशुआ डी। बॉयड

5
i ** 3 भी i * i * i के बराबर है
ब्रीजर

5
@ ब्रीजर वास्तव i**3में कॉल करेगा i.__pow__(3)और i*i*i i.__mul__(i).__mul__(i)(या ऐसा कुछ)। Ints के साथ यह कोई फर्क नहीं पड़ता, लेकिन संख्याओं / कस्टम वर्गों के साथ यह अलग परिणाम भी दे सकता है।
syntonym

1
मैंने देखा है कि जब भी हम सुनते हैं कि "गुइडो ने निर्णय एक्स" किया है, तो दर्द एक संभावित परिणाम है। यह एक महान उदाहरण है: list(list(list(.. )))क्या करने के लिए पहले से ही अजगर में क्रिया थी।
जावदबा

12

अन्य उत्तरों के परिशिष्ट के रूप में, यह एक संदर्भ प्रबंधक के लिए एक ठीक उपयोग के मामले जैसा लगता है जो इन कार्यों के नामों को उन लोगों के लिए फिर से मैप करेगा जो एक सूची लौटाते हैं और reduceवैश्विक नामस्थान में परिचय देते हैं ।

एक त्वरित कार्यान्वयन इस तरह दिख सकता है:

from contextlib import contextmanager    

@contextmanager
def noiters(*funcs):
    if not funcs: 
        funcs = [map, filter, zip] # etc
    from functools import reduce
    globals()[reduce.__name__] = reduce
    for func in funcs:
        globals()[func.__name__] = lambda *ar, func = func, **kwar: list(func(*ar, **kwar))
    try:
        yield
    finally:
        del globals()[reduce.__name__]
        for func in funcs: globals()[func.__name__] = func

एक उपयोग के साथ जो इस तरह दिखता है:

with noiters(map):
    from operator import add
    print(reduce(add, range(1, 20)))
    print(map(int, ['1', '2']))

कौन सा प्रिंट:

190
[1, 2]

बस मेरे 2 सेंट :-)


1
pythonएक भाषा के रूप में एक मेस है - लेकिन यह उत्कृष्ट पुस्तकालयों के लिए वी अच्छा है: numpy, pandas, statsmodelsऔर दोस्तों .. मैं सुविधा पुस्तकालयों buliding किया गया था जैसा आप यहां दिखाने के मूल भाषा के दर्द को कम करने के लिए - लेकिन ऊर्जा खो दिया है और के लिए नहीं की कोशिश की है a data.frame/ से दूर भटका datatable, या xarray। लेकिन कोशिश करने के लिए यश ..
javadba

7

चूंकि reduceपाइथन 3 से बिल्ट इन फंक्शन को विधि से हटा दिया गया है, इसलिए functoolsअपने कोड में आयात करना न भूलें । कृपया नीचे दिए गए कोड स्निपेट को देखें।

import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)

2

यहां फ़िल्टर, मानचित्र और कार्यों को कम करने के उदाहरण हैं।

संख्या = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]

// फ़िल्टर

विषमांक = सूची (फिल्टर (लंबो x: x% 2! = 0, संख्या))

प्रिंट (oddNumbers)

//नक्शा

multiplyOf2 = सूची (नक्शा (लंबो x: x * 2, संख्या))

प्रिंट (multiplyOf2)

//कम करना

कम होने वाला फ़ंक्शन, चूंकि इसका आमतौर पर उपयोग नहीं किया जाता है, पायथन 3 में अंतर्निहित कार्यों से हटा दिया गया था। यह अभी भी फंक्शंस के मॉड्यूल में उपलब्ध है, इसलिए आप कर सकते हैं:

ट्रांसफ़ॉर्मुल्स से आयात कम हो जाता है

योग = घटाएँ (लंबो x, y: x + y, संख्या)

प्रिंट (sumOfNumbers)


0

मानचित्र, फ़िल्टर और कम करने के फायदों में से एक यह है कि जब आप कुछ जटिल करने के लिए उन्हें एक साथ "चेन" करते हैं तो वे कितने सुपाठ्य हो जाते हैं। हालाँकि, अंतर्निहित सिंटैक्स सुपाठ्य नहीं है और सभी "बैकवर्ड" है। इसलिए, मेरा सुझाव है कि PyFunctionalपैकेज ( https://pypi.org/project/PyFunctional/ ) का उपयोग करेंयहाँ दो की तुलना है:

flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}

PyFunctional संस्करण

बहुत सुव्यवस्थित वाक्य रचना। तुम कह सकते हो:

"मेरे पास फ़्लाइट डेस्टिनेशंस का एक क्रम है। जिसमें से मैं अगर शहर को प्रमुख मूल्यों में रखना चाहता हूँ, तो अंत में मैं इस प्रक्रिया में बनाई गई खाली सूचियों को फ़िल्टर करना चाहता हूँ।"

from functional import seq  # PyFunctional package to allow easier syntax

def find_return_flights_PYFUNCTIONAL_SYNTAX(city, flight_destinations_dict):
    return seq(flight_destinations_dict.items()) \
        .map(lambda x: x[0] if city in x[1] else []) \
        .filter(lambda x: x != []) \

डिफ़ॉल्ट पायथन संस्करण

यह सब पीछे की तरफ है। आपको यह कहने की आवश्यकता है:

"ठीक है, इसलिए, एक सूची है। मैं इसमें से खाली सूचियों को फ़िल्टर करना चाहता हूं। क्यों? क्योंकि शहर को तानाशाही मूल्यों में रखने के कारण मुझे पहली बार प्रमुख कुंजी मिली। ओह, मैं जो सूची बना रहा हूं वह उड़ान_डिस्टेनेशन_डिक्ट है। "

def find_return_flights_DEFAULT_SYNTAX(city, flight_destinations_dict):
    return list(
        filter(lambda x: x != [],
               map(lambda x: x[0] if city in x[1] else [], flight_destinations_dict.items())
               )
    )
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.