अजगर मानचित्र और अन्य कार्यात्मक उपकरणों का उपयोग करना


127

यह काफी n00bish है, लेकिन मैं अजगर में कार्यात्मक प्रोग्रामिंग सीखने / समझने की कोशिश कर रहा हूं। निम्नलिखित कोड:

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest(foo, bar):
    print foo, bar

map(maptest, foos, bars)

पैदा करता है:

1.0 1
2.0 2
3.0 3
4.0 None
5.0 None

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

1.0 [1,2,3]
2.0 [1,2,3]
3.0 [1,2,3]
4.0 [1,2,3]
5.0 [1,2,3]

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

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3,4,5]

और प्रिंट करें:

1.0 [2,3,4,5]
2.0 [1,3,4,5]
3.0 [1,2,4,5]
...

पुनश्च: मैं जानता हूँ कि यह कैसे करना है अगर, छोरों और / या जनरेटर का उपयोग करके, लेकिन मैं यह सीखना चाहूंगा कि कार्यात्मक उपकरणों का उपयोग करके इसे कैसे प्राप्त किया जाए। क्या यह सिर्फ एक बयान जोड़ने का मामला है अगर maptest या आंतरिक रूप से maptest के बार में एक और फ़िल्टर मानचित्र लागू करें?


धन्यवाद दोस्तों। मुझे स्वीकार करना चाहिए कि मैं अजगर के माध्यम से कार्यात्मक प्रोग्रामिंग की अवधारणाओं को सीखने की कोशिश कर रहा हूं।

1
इसके लिए एक अच्छा ट्यूटोरियल यहाँ: Dreamsyssoft.com/python-scripting-tutorial/…
Rocky

जवाबों:


54

सबसे आसान तरीका barsविभिन्न कार्यों से गुजरना नहीं होगा , बल्कि इसे सीधे यहां से एक्सेस करना होगा maptest:

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest(foo):
    print foo, bars

map(maptest, foos)

अपने मूल maptestकार्य के साथ आप एक लंबो फ़ंक्शन का उपयोग भी कर सकते हैं map:

map((lambda foo: maptest(foo, bars)), foos)

बुरा तब होता है जब बार सूची में से आता है
फ़िओ अरकार एलविन

59
यह समाधान सीधे कार्यात्मक प्रोग्रामिंग के सिद्धांतों के खिलाफ जाता है जिसे ओपी सीखने का प्रयास करना चाहता है। फ़ंक्शनल प्रोग्रामिंग में एक मौलिक नियम यह है कि हर बार जब आप एक ही तर्कों के साथ एक फ़ंक्शन कहते हैं, तो आप हमेशा एक ही आउटपुट प्राप्त करते हैं। यह वैश्विक राज्य होने के द्वारा शुरू किए गए कीड़े के एक वाइपर घोंसले से बचा जाता है। चूंकि maptest सलाखों की बाहरी परिभाषा पर निर्भर करता है, इसलिए यह सिद्धांत टूट गया है।
image_doctor

3
प्रिय स्टैक अतिप्रवाह, चूंकि आप प्रश्नों को बंद करना पसंद करते हैं और मध्यम रूप से भारी हैं, इसलिए आप इस प्रश्न को उत्तर के रूप में चिह्नित नहीं करते हैं और उत्तर के रूप में सही प्रतिक्रिया को चिह्नित करते हैं? सादर, हमें।
बहादुर कांबेल

1
@image_doctor, FP में वैश्विक स्थिरांक का उपयोग करना पूरी तरह से ठीक है (वहाँ अशक्त नलिका के रूप में संबंध)
पीटर के

1
@BahadirCambel स्टैक ओवरफ्लो मॉडरेशन कभी-कभी भारी-भरकम हो सकता है, लेकिन चेकमार्क हमेशा, और हमेशा ओपी से संबंधित होगा।
wizzwizz4

194

क्या आप अन्य कार्यात्मक भाषाओं से परिचित हैं? यानी आप यह जानने की कोशिश कर रहे हैं कि पायथन कार्यात्मक प्रोग्रामिंग कैसे करता है, या क्या आप कार्यात्मक प्रोग्रामिंग के बारे में जानने की कोशिश कर रहे हैं और वाहन के रूप में अजगर का उपयोग कर रहे हैं?

इसके अलावा, क्या आप सूची समझ समझ रहे हैं?

map(f, sequence)

के बराबर है (*):

[f(x) for x in sequence]

वास्तव में, मुझे लगता है map()कि एक बार अजगर 3.0 से निरर्थक होने के कारण हटा दिया गया था (ऐसा नहीं हुआ)।

map(f, sequence1, sequence2)

ज्यादातर इसके बराबर है:

[f(x1, x2) for x1, x2 in zip(sequence1, sequence2)]

(इसमें एक अंतर है कि यह उस मामले को कैसे संभालता है जहां अनुक्रम अलग-अलग लंबाई के होते हैं। जैसा कि आपने देखा, map()किसी में भी कोई नहीं भरता है जब अनुक्रम में से एक चलता है, जबकि zip()सबसे कम अनुक्रम बंद हो जाता है)

इसलिए, अपने विशिष्ट प्रश्न को संबोधित करने के लिए, आप परिणाम का प्रयास कर रहे हैं:

foos[0], bars
foos[1], bars
foos[2], bars
# etc.

आप ऐसा एक फ़ंक्शन लिखकर कर सकते हैं जो एकल तर्क लेता है और उसे प्रिंट करता है, उसके बाद बार:

def maptest(x):
     print x, bars
map(maptest, foos)

वैकल्पिक रूप से, आप एक सूची बना सकते हैं जो इस तरह दिखती है:

[bars, bars, bars, ] # etc.

और अपने मूल maptest का उपयोग करें:

def maptest(x, y):
    print x, y

ऐसा करने का एक तरीका यह होगा कि आप पहले से सूची का निर्माण करें।

barses = [bars] * len(foos)
map(maptest, foos, barses)

वैकल्पिक रूप से, आप itertoolsमॉड्यूल में खींच सकते हैं । itertoolsअजगर में कार्यात्मक-शैली आलसी-मूल्यांकन प्रोग्रामिंग करने में मदद करने वाले कई चतुर कार्य शामिल हैं। इस मामले में, हम चाहते हैं itertools.repeat, जो इसके तर्क को अनिश्चित काल के लिए आउटपुट कर देगा क्योंकि आप इस पर पुनरावृति करेंगे। इस अंतिम तथ्य का अर्थ है कि यदि आप करते हैं:

map(maptest, foos, itertools.repeat(bars))

आपको अंतहीन आउटपुट मिलेगा, क्योंकि जब map()तक कोई एक तर्क अभी भी उत्पादन कर रहा है , तब तक चलता रहेगा । हालाँकि, itertools.imapजैसा है map(), लेकिन जैसे ही सबसे छोटा चलना बंद हो जाता है।

itertools.imap(maptest, foos, itertools.repeat(bars))

उम्मीद है की यह मदद करेगा :-)

(*) यह अजगर 3.0 में थोड़ा अलग है। वहां, नक्शा () अनिवार्य रूप से एक जनरेटर अभिव्यक्ति देता है।


तो, क्या मैं सही ढंग से समझ रहा हूं कि नक्शे के विपरीत, itertools.imap(f, sequence1, sequence2)वास्तव में इसके बराबर है [f(x1, x2) for x1, x2 in zip(sequence1, sequence2)]?
जॉन Coombs

थोड़ा परीक्षण, मैं देखता हूं कि यह एक itertools.imap वस्तु लौटाता है, इसलिए शायद यह अधिक 'समतुल्य' होगा:list(itertools.imap(f, sequence1, sequence2))
जॉन Coombs

यह स्वीकृत उत्तर होना चाहिए।
रॉ ग्रांट

30

यहां वह समाधान है जिसकी आप तलाश कर रहे हैं:

>>> foos = [1.0, 2.0, 3.0, 4.0, 5.0]
>>> bars = [1, 2, 3]
>>> [(x, bars) for x in foos]
[(1.0, [1, 2, 3]), (2.0, [1, 2, 3]), (3.0, [1, 2, 3]), (4.0, [1, 2, 3]), (5.0, [
1, 2, 3])]

मैं सूची का उपयोग करके एक सूची समझ ( [(x, bars) for x in foos]भाग) का उपयोग करने की सलाह दूंगा क्योंकि यह प्रत्येक पुनरावृत्ति (जो बहुत महत्वपूर्ण हो सकता है) पर एक फ़ंक्शन कॉल के ओवरहेड से बचा जाता है। यदि आप इसे लूप के लिए उपयोग करने जा रहे हैं, तो आपको जनरेटर की समझ का उपयोग करके बेहतर गति मिलेगी:

>>> y = ((x, bars) for x in foos)
>>> for z in y:
...     print z
...
(1.0, [1, 2, 3])
(2.0, [1, 2, 3])
(3.0, [1, 2, 3])
(4.0, [1, 2, 3])
(5.0, [1, 2, 3])

अंतर यह है कि जनरेटर की समझ आलस्य से भरी हुई है

अद्यतन इस टिप्पणी के जवाब में:

निश्चित रूप से आप जानते हैं, कि आप बार को कॉपी नहीं करते हैं, सभी प्रविष्टियाँ समान बार सूची हैं। इसलिए यदि आप उनमें से किसी एक (मूल सलाखों सहित) को संशोधित करते हैं, तो आप उन सभी को संशोधित करते हैं।

मुझे लगता है कि यह एक वैध बिंदु है। इसके दो उपाय हैं जिनके बारे में मैं सोच सकता हूं। सबसे कुशल शायद कुछ इस तरह है:

tbars = tuple(bars)
[(x, tbars) for x in foos]

चूंकि ट्यूप्स अपरिवर्तनीय हैं, इसलिए यह इस सूची के परिणामों (या यदि आप उस मार्ग पर जाते हैं तो जनरेटर की समझ) के परिणामों के माध्यम से सलाखों को संशोधित करने से रोकेंगे। यदि आपको वास्तव में परिणामों में से प्रत्येक को संशोधित करने की आवश्यकता है, तो आप ऐसा कर सकते हैं:

from copy import copy
[(x, copy(bars)) for x in foos]

हालाँकि, यह मेमोरी उपयोग और गति दोनों के लिहाज से थोड़ा महंगा हो सकता है, इसलिए मैं इसके खिलाफ सिफारिश करूंगा जब तक कि आपको उनमें से हर एक को जोड़ने की आवश्यकता न हो।


1
निश्चित रूप से आप जानते हैं, कि आप बार को कॉपी नहीं करते हैं, सभी प्रविष्टियाँ समान बार सूची हैं। इसलिए यदि आप उनमें से किसी एक (मूल सलाखों सहित) को संशोधित करते हैं, तो आप उन सभी को संशोधित करते हैं।
vartec

20

कार्यात्मक प्रोग्रामिंग साइड-इफ़ेक्ट-फ्री कोड बनाने के बारे में है।

नक्शा एक कार्यात्मक सूची परिवर्तन अमूर्तता है। आप इसका उपयोग किसी चीज़ के अनुक्रम को लेने के लिए करते हैं और इसे किसी अन्य चीज़ के अनुक्रम में बदलते हैं।

आप इसे एक पुनरावृत्त के रूप में उपयोग करने का प्रयास कर रहे हैं। ऐसा मत करो। :)

यहाँ एक उदाहरण है कि आप अपनी इच्छित सूची बनाने के लिए मानचित्र का उपयोग कैसे कर सकते हैं। छोटे समाधान हैं (मैं बस समझ का उपयोग करूँगा), लेकिन इससे आपको यह समझने में मदद मिलेगी कि मानचित्र थोड़ा बेहतर क्या है:

def my_transform_function(input):
    return [input, [1, 2, 3]]

new_list = map(my_transform, input_list)

इस बिंदु पर सूचना, आपने केवल एक डेटा हेरफेर किया है। अब आप इसे प्रिंट कर सकते हैं:

for n,l in new_list:
    print n, ll

- मुझे यकीन नहीं है कि आपका मतलब क्या है 'बिना छोरों के।' fp लूप्स से बचने के बारे में नहीं है (आप प्रत्येक सूची में प्रत्येक आइटम की जांच नहीं कर सकते हैं)। यह साइड-इफ़ेक्ट से बचने के बारे में है, इस प्रकार कम बग्स लिखते हैं।



11
import itertools

foos=[1.0, 2.0, 3.0, 4.0, 5.0]
bars=[1, 2, 3]

print zip(foos, itertools.cycle([bars]))

यह सबसे आसान और सही ढंग से कार्यात्मक है। कृपया इसे उत्तर के रूप में स्वीकार करें
Phyo Arkar Lwin

1
यह सिर्फ कोड है। कोई स्पष्टीकरण नहीं है। कई उपयोगकर्ताओं को समझ में नहीं आता कि इस उत्तर का क्या अर्थ है। @PhyoArkarLwin
ProgramFast

6

यहां map(function, *sequences)फ़ंक्शन के मापदंडों का अवलोकन किया गया है:

  • function आपके फ़ंक्शन का नाम है।
  • sequencesकिसी भी संख्या में अनुक्रम होते हैं, जो आमतौर पर सूचियाँ या टुपल्स होते हैं। एक साथmap उन पर पुनरावृति करेगा और वर्तमान मानों को देगा । इसलिए अनुक्रमों की संख्या आपके फ़ंक्शन के मापदंडों की संख्या के बराबर होनी चाहिए।function

ऐसा लगता है कि आप कुछ functionमापदंडों के लिए पुनरावृति करने की कोशिश कर रहे हैं , लेकिन दूसरों को स्थिर रखते हैं, और दुर्भाग्य से mapइसका समर्थन नहीं करता है। मुझे मिलापायथन में इस तरह की सुविधा को जोड़ने के लिए एक पुराना प्रस्ताव , लेकिन मानचित्र का निर्माण इतना साफ और सुव्यवस्थित है कि मुझे संदेह है कि ऐसा कुछ कभी लागू होगा।

वैश्विक चर या सूची समझ जैसे वर्कअराउंड का उपयोग करें, जैसा कि अन्य ने सुझाव दिया है।


0

यह करोगे?

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest2(bar):
  print bar

def maptest(foo):
  print foo
  map(maptest2, bars)

map(maptest, foos)

1
आप maptest2 के लिए परम को कॉल करना चाह सकते हैं () 'बार' की तरह कुछ। विलक्षण का barतात्पर्य है कि जब आप वास्तव में पूरी सूची चाहते हैं, तो इसे एक मान प्राप्त होता है।
निखिल चेलिया

1
यह वास्तव में मुझे विश्वास है कि एक iterated मूल्य प्राप्त कर रहा है।
क्रिस

0

इस बारे में कैसा है:

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest(foo, bar):
    print foo, bar

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