मैं इस दोनों कार्यों से fold()
और reduce()
कोटलिन में बहुत भ्रमित हूं , क्या कोई मुझे एक ठोस उदाहरण दे सकता है जो दोनों को अलग करता है?
मैं इस दोनों कार्यों से fold()
और reduce()
कोटलिन में बहुत भ्रमित हूं , क्या कोई मुझे एक ठोस उदाहरण दे सकता है जो दोनों को अलग करता है?
जवाबों:
fold
एक प्रारंभिक मूल्य लेता है, और आपके द्वारा पास किए गए लैम्ब्डा का पहला आह्वान उस प्रारंभिक मूल्य और पैरामीटर के संग्रह का पहला तत्व प्राप्त करेगा।
उदाहरण के लिए, निम्न कोड लें जो पूर्णांकों की सूची के योग की गणना करता है:
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
लैम्ब्डा के लिए पहली कॉल मापदंडों 0
और के साथ होगी 1
।
यदि आपको अपने ऑपरेशन के लिए किसी प्रकार का डिफ़ॉल्ट मान या पैरामीटर प्रदान करना है, तो प्रारंभिक मूल्य में पास होने की क्षमता होना उपयोगी है। उदाहरण के लिए, यदि आप किसी सूची के अंदर अधिकतम मूल्य की तलाश कर रहे थे, लेकिन किसी कारण से कम से कम 10 पर वापस जाना चाहते हैं, तो आप निम्नलिखित कार्य कर सकते हैं:
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reduce
एक प्रारंभिक मूल्य नहीं लेता है, लेकिन इसके बजाय संचयकर्ता के रूप में संग्रह के पहले तत्व के साथ शुरू होता है ( sum
निम्नलिखित उदाहरण में कहा जाता है)।
उदाहरण के लिए, आइए फिर से पूर्णांक का योग करें:
listOf(1, 2, 3).reduce { sum, element -> sum + element }
यहां लंबोदर का पहला कॉल मापदंडों 1
और के साथ होगा 2
।
आप उपयोग कर सकते हैं reduce
जब आपका ऑपरेशन उस संग्रह के अलावा किसी भी मान पर निर्भर नहीं करता है जिसे आप इसे लागू कर रहे हैं।
emptyList<Int>().reduce { acc, s -> acc + s }
एक अपवाद का उत्पादन करेगा, लेकिन emptyList<Int>().fold(0) { acc, s -> acc + s }
ठीक है।
listOf<Int>(1, 2).reduce { acc: Number, i: Int -> acc.toLong() + i }
(सूची-प्रकार इंट है जबकि संचायक प्रकार को संख्या के रूप में घोषित किया जाता है और वास्तव में एक लंबा होता है)
प्रमुख कार्यात्मक अंतर जिसे मैं बाहर कॉल करूंगा (जो अन्य उत्तर पर टिप्पणियों में उल्लिखित है, लेकिन समझना मुश्किल हो सकता है) यह है कि एक खाली संग्रह पर प्रदर्शन किए जाने पर एक reduce
अपवाद फेंक दिया जाएगा ।
listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.
इसका कारण यह है कि .reduce
"कोई डेटा नहीं" की स्थिति में वापस जाने के लिए क्या मूल्य है।
इसके साथ विरोधाभास करें .fold
, जिसके लिए आपको "प्रारंभिक मूल्य" प्रदान करना होगा, जो खाली संग्रह की स्थिति में डिफ़ॉल्ट मान होगा:
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
इसलिए, भले ही आप अपने संग्रह को किसी भिन्न (गैर-संबंधित) प्रकार के एकल तत्व तक सीमित नहीं करना चाहते (जो केवल .fold
आपको करने देगा), यदि आपका प्रारंभिक संग्रह खाली हो सकता है, तो आपको या तो अपने संग्रह की जांच करनी चाहिए आकार पहले और फिर .reduce
, या बस उपयोग करें.fold
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)