, आप कर सकते हैं follow a set of small steps to refector to a recursive implementation:
let groupFunc list =
let rec groupFuncRec acc lst init count =
match lst with
| [] -> List.rev acc
| head::[] when head = init
-> groupFuncRec ((init, count)::acc) [] 0 0
| head::[] when head <> init
-> groupFuncRec ((head, 1)::acc) [] 0 0
| head::tail when head = init
-> groupFuncRec acc tail head (count+1)
| head::tail when head <> init
-> groupFuncRec ((init, count)::acc) tail head 1
let t = List.tail list
let h = List.head list
groupFuncRec [] t h 1
जब मैं अपने नमूना डेटा पर समारोह को चलाने मैं वापस अपेक्षित परिणाम मिलता है।
Recursion
जब मैं अपने जरूरी संस्करण की तरह, यहाँ एक पुनरावर्ती संस्करण है लग रहा है क्या पता नहीं है:
let pack xs =
let rec imp acc = function
| [] -> acc
| h::t ->
match acc with
| [] -> imp [(h, 1)] t
| (i, count) :: ta ->
if h = i
then imp ((i, count + 1) :: ta) t
else imp ((h, 1) :: (i, count) :: ta) t
xs |> imp [] |> List.rev
इस समारोह प्रकार 'a list -> ('a * int) list when 'a : equality
है। यह काम करने के लिए imp
नामक एक निजी 'कार्यान्वयन समारोह' का उपयोग करता है। यह फ़ंक्शन रिकर्सिव है, और थ्रेड एक संचयक (जिसे acc
कहा जाता है) पूरे होते हैं। यह संचयक परिणाम सूची है, जिसमें ('a * int) list
है।
तो संचायक सूची खाली है, मूल सूची (h
) के प्रमुख के रूप में भी गिनती 1
, अद्यतन संचायक का एकमात्र ऐसा तत्व के रूप में एक टपल के रूप में बनाया गया है, और imp
समारोह रिकर्सिवली साथ कहा जाता है वह अद्यतन संचयक।
यदि संचयक में पहले से ही कम से कम एक तत्व होता है, तो तत्व पैटर्न मिलान के माध्यम से निकाला जाता है, और उस ट्यूपल (i
) में तत्व h
से तुलना किया जाता है। यदि h = i
, संचयक अद्यतन किया गया है; अन्यथा, acc
पर एक नया ट्यूपल लगाया जाता है। दोनों मामलों में, हालांकि, imp
को नए संचयक के साथ दोबारा बुलाया जाता है।
आप एक सूची इस तरह अपने मूल टपल के बराबर से कॉल करने की कर सकते हैं:
> pack [1; 2; 2; 3; 2; 2; 2; 4];;
val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
फोल्ड
एक बार जब आप एक पुनरावर्ती संस्करण है, तो आप अक्सर एक संस्करण के लिए नुस्खा एक का उपयोग कर तह। इस मामले में, उपर्युक्त pack
फ़ंक्शन को अंत में संचयक को पीछे हटाना है (List.rev
का उपयोग करके), दाएं गुना सबसे उपयुक्त है।एफ # में, इस के साथ निर्मित List.foldBack
समारोह किया जाता है:
let pack' xs =
let imp x = function
| (i, count) :: ta when i = x -> (i, count + 1) :: ta
| ta -> (x, 1) :: ta
List.foldBack imp xs []
इस मामले में, समारोह List.foldBack
के लिए पारित एक सा भी एक गुमनाम समारोह के रूप में पारित करने के लिए जटिल है, इसलिए मैं एक के रूप में यह परिभाषित करने के लिए चुना है निजी आंतरिक समारोह। यह उपरोक्त pack
फ़ंक्शन द्वारा उपयोग किए गए रिकर्सिव imp
फ़ंक्शन के समतुल्य है, लेकिन आप यह स्वीकार करेंगे कि इसे स्वयं को रिकर्सिव रूप से कॉल करने की आवश्यकता नहीं है। इसके बजाय, इसे केवल संचयक के लिए नया मूल्य वापस करना होगा।
परिणाम एक ही है:
> pack' [1; 2; 2; 3; 2; 2; 2; 4];;
val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
अच्छा जवाब। मेरी राय में कुछ चीजें छोटे बदलाव इसे और भी स्पष्ट कर सकती हैं। आप पहचानने वाले नामक से बचने के लिए 'let imp x acc = match acc ...' के साथ 'let imp x acc = match acc ...' को प्रतिस्थापित कर सकते हैं जिसे आप तुरंत तुरंत नष्ट कर देते हैं। सबसे महत्वपूर्ण बात यह है कि आप पैटर्न मिलान के मामलों के क्रम को स्विच कर सकते हैं और '[]' और 'x <> i' मामलों को एकीकृत करने के लिए 'कब' खंड का उपयोग कर सकते हैं:' | (मैं, गिनती) :: टा जब मैं = एक्स -> (i, गिनती + 1) :: टा टा -> (एक्स, 1) :: टा'। – kvb
@kvb वे बहुत अच्छे सरलीकरण हैं! धन्यवाद। उत्तर अपडेट किया गया। –