2012-04-28 28 views
88

क्या निम्नलिखित की तरह कुछ, हास्केल में प्राप्त करने के लिए सबसे मुहावरेदार तरीका है:कार्यात्मक प्रोग्रामिंग से 'फोल्ड' फ़ंक्शन के समतुल्य 'पायथनिक' क्या है?

foldl (+) 0 [1,2,3,4,5] 
--> 15 

या रूबी में उसके बराबर:

[1,2,3,4,5].inject(0) {|m,x| m + x} 
#> 15 

जाहिर है, अजगर reduce समारोह प्रदान करता है, एक कार्यान्वयन है जो ठीक है, ठीक है, हालांकि, मुझे बताया गया था कि प्रोग्रामिंग का 'पायथनिक' तरीका lambda नियमों और उच्च-आदेश कार्यों से बचने के लिए था, जहां संभव हो वहां सूची-समझों को पसंद करना था। इसलिए, क्या एक सूची को फोल्ड करने का एक पसंदीदा तरीका है, या पायथन में सूची जैसी संरचना है जो reduce फ़ंक्शन नहीं है, या reduce यह प्राप्त करने का मूर्ख तरीका है?

+2

'sum' पर्याप्त नहीं है? – JBernardo

+3

सुनिश्चित नहीं है कि यह आपके प्रश्न के लिए एक अच्छा उदाहरण है। इसे आसानी से 'योग' के साथ हासिल किया जा सकता है, आप कुछ अलग-अलग प्रकार के उदाहरण प्रदान करना चाह सकते हैं। – jamylak

+10

हे जेबर्नर्डो - संख्याओं की एक सूची में सम्मिलित करना एक अपमानजनक उदाहरण के रूप में था, मुझे कुछ बाइनरी ऑपरेशन का उपयोग करके सूची के तत्वों को जमा करने के सामान्य विचार में और अधिक प्रारंभिक मूल्य, विशेष रूप से पूर्णांक को संक्षेप में नहीं समझा जाता है। – mistertim

उत्तर

93

एक सरणी को जोड़ने का पाइथोनिक तरीका sum है। अन्य उद्देश्यों के लिए, आप कभी-कभी reduce और operator मॉड्यूल के कुछ संयोजन का उपयोग कर सकते हैं, उदा।

def product(xs): 
    return reduce(operator.mul, xs, 1) 

जानते हैं कि वास्तव में एक reducefoldl है, हास्केल मामले में रहें। फ़ोल्ड करने के लिए कोई विशेष वाक्यविन्यास नहीं है, कोई निर्मित foldr नहीं है, और वास्तव में reduce का उपयोग गैर-सहयोगी ऑपरेटरों को खराब शैली माना जाता है।

उच्च-आदेश कार्यों का उपयोग करना काफी पाइथनिक है; यह पायथन के सिद्धांत का अच्छा उपयोग करता है कि सबकुछ एक वस्तु है, जिसमें कार्य और कक्षाएं शामिल हैं। आप सही हैं कि कुछ पाइथोनिस्टस द्वारा लैम्ब्डा फेंकते हैं, लेकिन अधिकतर क्योंकि वे जटिल होने पर बहुत पठनीय नहीं होते हैं।

+0

उच्च-आदेश फ़ंक्शन हमेशा पाइथनिक नहीं हो सकते हैं। अन्यथा पीई 3 के बिल्टिन नेमस्पेस से 'कम करें' क्यों हटाया जाएगा? – JBernardo

+3

@ जेबेर्नर्डो: आप कह रहे हैं कि बिल्टिन मॉड्यूल में कुछ भी नहीं है pythonic? –

+3

नहीं, यह कहना बेवकूफ होगा। लेकिन मुझे एक कारण बताएं कि आप क्यों सोचते हैं [जीवीआर इतनी कम काम से नफरत करेगा] (http://www.artima.com/weblogs/viewpost.jsp?thread=98196) इसे बिल्टिन से हटाने के बिंदु पर? – JBernardo

3

इस (कम) समस्या का वास्तविक उत्तर है: बस एक लूप का उपयोग करें!

initial_value = 0 
for x in the_list: 
    initial_value += x #or any function. 

यह तुलना में तेजी से हो जाएगा एक कम करने और PyPy तरह बातें उस तरह छोरों अनुकूलन कर सकते हैं।

Btw, योग मामले sum समारोह

+4

इसे इस तरह के उदाहरण के लिए पायथनिक नहीं माना जाएगा। – jamylak

+7

पायथन लूप कुख्यात धीमी हैं।पाइथन प्रोग्राम को अनुकूलित करने का एक आम तरीका है 'कम करना' का उपयोग करना (या दुरुपयोग करना)। –

+2

@jamylak मैंने फिर से लिखा अंतिम पंक्ति पढ़ें .... – JBernardo

3

के साथ हल किया जाना चाहिए साथ ही आप पहिया बदलने कर सकते हैं:

def fold(f, l, a): 
    """ 
    f: the function to apply 
    l: the list to fold 
    a: the accumulator, who is also the 'zero' on the first call 
    """ 
    return a if(len(l) == 0) else fold(f, l[1:], f(a, l[0])) 

print "Sum:", fold(lambda x, y : x+y, [1,2,3,4,5], 0) 

print "Any:", fold(lambda x, y : x or y, [False, True, False], False) 

print "All:", fold(lambda x, y : x and y, [False, True, False], True) 

# Prove that result can be of a different type of the list's elements 
print "Count(x==True):", 
print fold(lambda x, y : x+1 if(y) else x, [False, True, True], 0) 
+0

आप अपने रिकर्सिव केस में तर्कों को 'f' के आसपास स्वैप करते हैं। – KayEss

+6

क्योंकि पाइथन में पूंछ रिकर्सन की कमी है, यह लंबी सूचियों पर टूट जाएगा और अपर्याप्त है। इसके अलावा, यह वास्तव में "गुना" फ़ंक्शन नहीं है, लेकिन केवल बाएं गुना, यानी फ़ोल्डल, यानी, * वास्तव में * पहले से क्या 'कम करता है' (ध्यान दें कि फ़ंक्शन हस्ताक्षर को कम करना 'कम है (फ़ंक्शन, अनुक्रम [प्रारंभिक]) -> मूल्य' - यह भी, संचयक के लिए प्रारंभिक मूल्य देने की कार्यक्षमता शामिल है)। – cemper93

12

हास्केल

foldl (+) 0 [1,2,3,4,5]

अजगर

reduce(lambda a,b: a+b, [1,2,3,4,5], 0)

जाहिर है, यह एक बिंदु को चित्रित करने के लिए एक मामूली उदाहरण है। पायथन में आप केवल sum([1,2,3,4,5]) करेंगे और यहां तक ​​कि हास्केल purists भी आमतौर पर sum [1,2,3,4,5] पसंद करेंगे।

गैर तुच्छ परिदृश्यों के लिए जब कोई स्पष्ट सुविधा समारोह है वहाँ, मुहावरेदार pythonic दृष्टिकोण स्पष्ट रूप से पाश के लिए बाहर लिख सकते हैं और बजाय reduce या एक fold का उपयोग करने का परिवर्तनशील चर काम का प्रयोग है।

यह सभी कार्यात्मक शैली में नहीं है, लेकिन यह "पायथनिक" तरीका है। पाइथन कार्यात्मक शुद्धवादियों के लिए डिज़ाइन नहीं किया गया है। देखें कि कैसे पाइथन प्रवाह नियंत्रण के लिए अपवादों का पक्ष लेता है यह देखने के लिए कि गैर-कार्यात्मक मुहावरेदार पायथन कैसा है।

+1

गुना कार्यात्मक "purists" से अधिक के लिए उपयोगी हैं। वे सामान्य उद्देश्य abstractions हैं। कंप्यूटिंग में पुनरावर्ती समस्याएं व्यापक हैं। फोल्ड बॉयलरप्लेट को हटाने और उन भाषाओं में रिकर्सिव समाधान सुरक्षित करने का एक तरीका प्रदान करते हैं जो नकारात्मक रूप से पुनरावृत्ति का समर्थन नहीं करते हैं। तो एक बहुत ही व्यावहारिक बात है। इस क्षेत्र में जीवीआर के पूर्वाग्रह दुर्भाग्यपूर्ण हैं। – itsbruce

3

नहीं वास्तव में सवाल का जवाब है, लेकिन foldl और foldr के लिए एक लाइनर्स:

a = [8,3,4] 

## Foldl 
reduce(lambda x,y: x**y, a) 
#68719476736 

## Foldr 
reduce(lambda x,y: y**x, a[::-1]) 
#14134776518227074636666380005943348126619871175004951664972849610340958208L 
6

अजगर 3 में, reduce हटा दिया गया है: Release notes। फिर भी आप functools module

import operator, functools 
def product(xs): 
    return functools.reduce(operator.mul, xs, 1) 

उपयोग कर सकते हैं दूसरी ओर, प्रलेखन reduce के बजाय for -loop की ओर वरीयता व्यक्त करता है, इसलिए:

def product(xs): 
    result = 1 
    for i in xs: 
     result *= i 
    return result 
+1

'कम करें' पायथन 3 मानक लाइब्रेरी से नहीं हटाया गया था। जैसा कि आप दिखाते हैं, 'कम करें' 'functools' मॉड्यूल में ले जाया गया। – clay

+0

@clay, मैंने अभी गिडो के रिलीज नोट्स से वाक्यांश लिया है, लेकिन आप सही हो सकते हैं :) – Kyr

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^