Scala में foldLeft और lessLeft के बीच अंतर


196

मैंने foldLeftऔर के बीच बुनियादी अंतर सीखा हैreduceLeft

foldLeft:

  • प्रारंभिक मूल्य पारित करना होगा

reduceLeft:

  • प्रारंभिक मूल्य के रूप में संग्रह का पहला तत्व लेता है
  • यदि संग्रह खाली है तो अपवाद फेंकता है

क्या कोई और अंतर है?

समान कार्यक्षमता के साथ दो तरीके होने का कोई विशेष कारण?


अनुशंसा करें कि आप stackoverflow.com/questions/25158780/…
samthebest

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

जवाबों:


303

वास्तविक उत्तर देने से पहले कुछ बातों का उल्लेख यहां करें:

  • आपके प्रश्न का कोई लेना-देना नहीं है left, यह कम करने और तह करने के बीच के अंतर के बारे में है
  • अंतर बिल्कुल कार्यान्वयन नहीं है, बस हस्ताक्षर देखें।
  • यह सवाल विशेष रूप से स्काला के साथ कुछ भी नहीं करता है, यह कार्यात्मक प्रोग्रामिंग की दो अवधारणाओं के बारे में है।

अपने प्रश्न पर वापस जाएं:

यहाँ पर foldLeft( foldRightजिस बिंदु को मैं करने जा रहा हूँ , उस पर हस्ताक्षर भी हो सकते हैं):

def foldLeft [B] (z: B)(f: (B, A) => B): B

और यहाँ पर हस्ताक्षर है reduceLeft (फिर से दिशा यहाँ कोई फर्क नहीं पड़ता)

def reduceLeft [B >: A] (f: (B, A) => B): B

ये दोनों बहुत समान दिखते हैं और इस तरह भ्रम पैदा करते हैं। reduceLeftका एक विशेष मामला है foldLeft(जिस तरह से इसका मतलब है कि आप कभी-कभी दोनों में से किसी एक का उपयोग करके एक ही बात व्यक्त कर सकते हैं)।

जब आप कहते reduceLeftहैं एक परList[Int] इसे यह पूर्णांकों की पूर्ण सूची को सचमुच एक ही मूल्य में कम कर देगा, जो कि प्रकार का हो रहा है Int(या इसका एक प्रकारांतर ) Int, इसलिए [B >: A]

जब तुमने फोन किया foldLeft कि List[Int]यह पूरी सूची को मोड़ देगा (एक कागज के टुकड़े को रोल करने की कल्पना करें) एक ही मूल्य में, लेकिन यह मान भी इससे संबंधित नहीं है Int(इसलिए [B])।

यहाँ एक उदाहरण है:

def listWithSum(numbers: List[Int]) = numbers.foldLeft((List.empty[Int], 0)) {
   (resultingTuple, currentInteger) =>
      (currentInteger :: resultingTuple._1, currentInteger + resultingTuple._2)
}

यह विधि एक लेता है List[Int]और रिटर्न एक Tuple2[List[Int], Int]या(List[Int], Int) । यह राशि की गणना करता है और पूर्णांक की सूची के साथ एक टपल लौटाता है और यह राशि है। वैसे सूची को पीछे की ओर लौटाया जाता है, क्योंकि हम foldLeftइसके बजाय इस्तेमाल करते हैं foldRight

गहराई से स्पष्टीकरण में अधिक के लिए उन सभी पर शासन करने के लिए एक गुना देखें ।


क्या आप बता सकते हैं कि Bइसका सुपरथाइप क्यों है A? ऐसा लगता है जैसे Bवास्तव में एक उपप्रकार होना चाहिए A, न कि कोई सुपर-टाइप। उदाहरण के लिए, यह मानते हुए Banana <: Fruit <: Food, यदि हमारे पास सूची है Fruit, तो ऐसा लगता है कि इसमें कुछ Bananas हो सकते हैं , लेकिन यदि इसमें कोई Foods समाहित है Food, तो प्रकार सही होगा? तो इस मामले में, यदि Bएक सुपरपाइप है Aऔर इसमें Bएस और Aएस दोनों की सूची है, तो सूची टाइप की जानी चाहिए B, न कि टाइप की A। क्या आप इस विसंगति की व्याख्या कर सकते हैं?
सोशोम 1880

मुझे यकीन नहीं है कि अगर मैं आपके सवाल को सही ढंग से समझूं। मेरे 5 साल के उत्तर को कम करने के समारोह के बारे में क्या कहा जा रहा है कि List[Banana]एक एकल Bananaया एक एकल Fruitया एकल को कम किया जा सकता है Food। क्योंकि Fruit :> Bananaऔर `भोजन:> केला’।
अगिलस्टील

हाँ ... यह वास्तव में समझदारी का धन्यवाद करता है। मैं मूल रूप से इसे "एक प्रकार की सूची में Bananaशामिल कर सकता हूं" की व्याख्या कर रहा था Fruit, जिसका कोई मतलब नहीं है। आपका स्पष्टीकरण समझ में आता है - fफ़ंक्शन को पास किया reduce()जा सकता है Fruitया Foodजिसके परिणामस्वरूप Bहस्ताक्षर का मतलब सुपरक्लास होना चाहिए, न कि उपवर्ग।
socom1880

193

reduceLeftबस एक सुविधा विधि है। के बराबर है

list.tail.foldLeft(list.head)(_)

11
अच्छा, संक्षिप्त उत्तर :) हो सकता है कि reducelftहालांकि वर्तनी में सुधार हो
हनक्स्यू

10
अच्छा उत्तर। यह इस बात पर भी प्रकाश डालता है कि foldखाली सूची में काम क्यों reduceनहीं होता है।
मंसूर सिद्दीकी 15

44

foldLeft अधिक सामान्य है, आप इसका उपयोग कर सकते हैं कि आप मूल रूप से जो कुछ भी डालते हैं, उससे पूरी तरह से अलग reduceLeft केवल एक ही प्रकार या सुपर प्रकार के संग्रह के अंतिम परिणाम का उत्पादन कर सकते हैं। उदाहरण के लिए:

List(1,3,5).foldLeft(0) { _ + _ }
List(1,3,5).foldLeft(List[String]()) { (a, b) => b.toString :: a }

foldLeftपिछले मुड़ा परिणाम के साथ बंद (पहली बार प्रारंभिक मूल्य का प्रयोग करके) और अगले मूल्य लागू होंगे।

reduceLeftदूसरी ओर पहले सूची से दो मानों को जोड़ेंगे और बंद करने वालों पर लागू करेंगे। अगला यह संचयी परिणाम के साथ बाकी मूल्यों को मिलाएगा। देख:

List(1,3,5).reduceLeft { (a, b) => println("a " + a + ", b " + b); a + b }

यदि सूची खाली है foldLeft, तो प्रारंभिक मूल्य को कानूनी परिणाम के रूप में प्रस्तुत किया जा सकता है। reduceLeftदूसरी ओर यदि कानूनी रूप से सूची में कम से कम एक मूल्य नहीं मिल सकता है तो उसके पास कोई कानूनी मूल्य नहीं है।


5

मूल कारण यह है कि वे स्काला मानक पुस्तकालय में दोनों कर रहे हैं शायद इसलिए है क्योंकि वे दोनों हास्केल में हैं मानक पुस्तकालय (कहा जाता है foldlऔर foldl1)। यदि reduceLeftऐसा नहीं होता, तो इसे अक्सर विभिन्न परियोजनाओं में सुविधा पद्धति के रूप में परिभाषित किया जाता।


5

संदर्भ के लिए, reduceLeftनिम्न त्रुटि के साथ एक खाली कंटेनर पर लागू होने पर त्रुटि होगी।

java.lang.UnsupportedOperationException: empty.reduceLeft

कोड का उपयोग करने के लिए

myList foldLeft(List[String]()) {(a,b) => a+b}

एक संभावित विकल्प है। एक अन्य reduceLeftOptionसंस्करण का उपयोग करना है जो एक विकल्प लिपटे परिणाम देता है।

myList reduceLeftOption {(a,b) => a+b} match {
  case None    => // handle no result as necessary
  case Some(v) => println(v)
}

2

से स्काला में कार्यात्मक प्रोग्रामिंग सिद्धांतों (मार्टिन ओडर्स्की):

समारोह reduceLeft, एक अधिक सामान्य समारोह के संदर्भ में परिभाषित किया गया है foldLeft

foldLeftकी तरह है reduceLeft, लेकिन एक लेता संचायक z एक अतिरिक्त पैरामीटर, जो जब लौटा दिया जाता है के रूप में, foldLeftएक खाली सूची पर कहा जाता है:

(List (x1, ..., xn) foldLeft z)(op) = (...(z op x1) op ...) op x

[जैसा कि विरोध किया गया है reduceLeft, जो एक खाली सूची पर बुलाए जाने पर एक अपवाद फेंकता है।]

पाठ्यक्रम (व्याख्यान 5.5 देखें) इन कार्यों की अमूर्त परिभाषा प्रदान करता है, जो उनके मतभेदों को दिखाता है, हालांकि वे पैटर्न मिलान और पुनरावृत्ति के अपने उपयोग में बहुत समान हैं।

abstract class List[T] { ...
  def reduceLeft(op: (T,T)=>T) : T = this match{
    case Nil     => throw new Error("Nil.reduceLeft")
    case x :: xs => (xs foldLeft x)(op)
  }
  def foldLeft[U](z: U)(op: (U,T)=>U): U = this match{
    case Nil     => z
    case x :: xs => (xs foldLeft op(z, x))(op)
  }
}

ध्यान दें कि foldLeftप्रकार का मान लौटाता है U, जो जरूरी नहीं कि उसी प्रकार का हो List[T], लेकिन कम करना, सूची के समान प्रकार का मान लौटाता है)।


0

वास्तव में समझने के लिए कि आप गुना / कम करने के साथ क्या कर रहे हैं, यह जांचें: http://wiki.tcl.tk/17983 बहुत अच्छी व्याख्या। एक बार जब आप गुना की अवधारणा प्राप्त करते हैं, तो ऊपर दिए गए उत्तर के साथ कम हो जाएगा: list.tail.foldLeft (list.head) (_)

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