2010-03-09 17 views
7

मैं एफ # सीखने की कोशिश कर रहा हूं। मैं पूरी तरह से शुरुआत कर रहा हूँ, तो यह आप लोग :)एफ # में वापसी मूल्य - अपूर्ण निर्माण

के लिए एक वाकओवर हो सकता है मैं निम्नलिखित कार्य हो:

let removeEven l = 
let n = List.length l; 
let list_ = []; 
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)} 
for x in seq_ do 
    let list_ = list_ @ [x]; 
list_; 

यह एक सूची लेता है, और सभी नंबरों को शामिल करते हुए एक नई सूची लौटने के लिए, जो मूल सूची में एक अजीब सूचकांक पर रखा गया है, इसलिए removeEven [x1;x2;x3] = [x1;x3]

हालांकि, मैं अपने पहले से ही पसंदीदा त्रुटि संदेश मिलता है: Incomplete construct at or before this point in expression...

मैं पंक्ति के अंत में एक प्रिंट जोड़ने के लिए, list_ के बजाय हैं:

... 
print_any list_; 

समस्या ठीक हो गई है। लेकिन मैं सूची मुद्रित नहीं करना चाहता, मैं वापसी चाहता हूं!

इसका क्या कारण है? मैं अपनी सूची क्यों नहीं लौटा सकता?

उत्तर

6

पहले अपने प्रश्न का उत्तर करने के लिए, संकलक शिकायत for पाश अंदर एक समस्या है क्योंकि वहाँ। एफ # में, let मूल्यों की घोषणा करने में कार्य करता है (जो अपरिवर्तनीय हैं और बाद में कार्यक्रम में नहीं बदला जा सकता है)। यह एक कथन नहीं है जैसा कि सी # - let में केवल एक अन्य अभिव्यक्ति के हिस्से के रूप में उपयोग किया जा सकता है। उदाहरण के लिए:

let n = 10 
n + n 

वास्तव में मतलब है कि आप n प्रतीक अभिव्यक्ति n + n में मूल्य 10 का उल्लेख करना चाहते हैं। - इस तरह से let का उपयोग कर अनुमति नहीं है

for x in seq_ do 
    let list_ = list_ @ [x] // This isn't assignment! 
list_ 

समस्याग्रस्त लाइन एक अधूरी अभिव्यक्ति है: अपने कोड के साथ समस्या यह है कि आप किसी भी अभिव्यक्ति के बिना let उपयोग कर रहे हैं (शायद इसलिए कि आप अस्थायी चर का उपयोग करना चाहते हैं) है , क्योंकि इसमें कोई अभिव्यक्ति नहीं है (list_ मान किसी भी कोड से नहीं पहुंचाया जाएगा)। आप अपने कोड को दूर करने के mutable चर का उपयोग कर सकते हैं:

let mutable list_ = [] // declared as 'mutable' 
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}  
for x in seq_ do  
    list_ <- list_ @ [x] // assignment using '<-' 

अब, यह काम करना चाहिए, लेकिन यह क्योंकि आप जरूरी उत्परिवर्तन का उपयोग कर रहे हैं, वास्तव में कार्यात्मक नहीं है। इसके अलावा, @ का उपयोग कर तत्वों को जोड़ना कार्यात्मक भाषाओं में वास्तव में अक्षम करने योग्य चीज है। इसलिए, यदि आप अपना कोड कार्यात्मक बनाना चाहते हैं, तो आपको शायद अलग-अलग दृष्टिकोण का उपयोग करने की आवश्यकता होगी। दोनों अन्य उत्तरों एक महान दृष्टिकोण दिखाते हैं, हालांकि मैं जोएल द्वारा उदाहरण पसंद करता हूं, क्योंकि सूची में अनुक्रमण (कैओस द्वारा समाधान में) भी बहुत कार्यात्मक नहीं है (कोई पॉइंटर अंकगणित नहीं है, इसलिए यह भी धीमा हो जाएगा) ।

शायद सबसे शास्त्रीय कार्यात्मक समाधान List.fold समारोह है, जो एक एकल परिणाम में सूची के सभी तत्वों को एकत्रित करती है, बाएं से सही करने के लिए चलने के लिए उपयोग करने के लिए होगा:

[1;2;3;4;5] 
    |> List.fold (fun (flag, res) el -> 
    if flag then (not flag, el::res) else (not flag, res)) (true, []) 
    |> snd |> List.rev 

इधर, राज्य के लिए इस्तेमाल किया दौरान एकत्रीकरण एक बूलियन फ़्लैग को निर्दिष्ट करके अगले तत्व शामिल करने के लिए है कि क्या है (प्रत्येक चरण के दौरान, हम not flag वापस लौट कर झंडा फ्लिप)। दूसरा तत्व अब तक एकत्रित सूची है (हम el::res द्वारा तत्व जोड़ते हैं, जब flag सेट होता है। fold रिटर्न के बाद, हम snd का उपयोग टुपल (समेकित सूची) का दूसरा तत्व प्राप्त करने के लिए करते हैं और List.rev का उपयोग करके इसे उलट देते हैं, क्योंकि यह उल्टा क्रम में एकत्र किया गया था (यह [email protected][el] का उपयोग कर अंत में जोड़ने से अधिक कुशल है)

+0

सूची का आकार = 1000; Iterations = 100; परिणाम (कैओसपैंडियन) = 4200ms; परिणाम (जोएल म्यूएलर) = 150ms; – ChaosPandion

+0

टॉमस की 'List.fold' दृष्टिकोण के बारे में कैसे? –

+0

वह लगभग 135 एमएमएस में आया था। – ChaosPandion

5

संपादित करें: यदि मैं आपकी आवश्यकताओं को सही ढंग से समझता हूं, तो यहां आपके कार्य का एक संस्करण अनिवार्य शैली के बजाय कार्यात्मक किया गया है, जो अजीब अनुक्रमणिका वाले तत्वों को हटा देता है।

let removeEven list = 
    list 
    |> Seq.mapi (fun i x -> (i, x)) 
    |> Seq.filter (fun (i, x) -> i % 2 = 0) 
    |> Seq.map snd 
    |> List.ofSeq 

> removeEven ['a'; 'b'; 'c'; 'd'];; 
val it : char list = ['a'; 'c'] 
+0

मैं का प्रयोग करेंगे 'Seq' व्यक्तिगत रूप से है। – ChaosPandion

+0

Does not को इस क्रम में विषम संख्या है, और नहीं नंबर, सरणी में एक अजीब सूचकांक पर रखा वापसी? (मैं इसे और अधिक स्पष्ट करने के लिए मूल पोस्ट संपादित करूंगा)। –

+0

मैं भी हो सकता है, लेकिन मैं '(पूर्णांक सूची -> पूर्णांक सूची) का इरादा विधि हस्ताक्षर से मेल करना चाहता था'। शायद एक कारण है कि फ्रेडरिक एक अनुक्रम की बजाय आउटपुट को सूची के रूप में चाहता है। –

2

मुझे लगता है कि यह वही है जो आप खोज रहे हैं।

let removeEven list = 
    let maxIndex = (List.length list) - 1; 
    seq { for i in 0..2..maxIndex -> list.[i] } 
    |> Seq.toList 

टेस्ट

val removeEven : 'a list -> 'a list 

> removeEven [1;2;3;4;5;6];; 
val it : int list = [1; 3; 5] 
> removeEven [1;2;3;4;5];; 
val it : int list = [1; 3; 5] 
> removeEven [1;2;3;4];; 
val it : int list = [1; 3] 
> removeEven [1;2;3];; 
val it : int list = [1; 3] 
> removeEven [1;2];; 
val it : int list = [1] 
> removeEven [1];; 
val it : int list = [1] 
0

आप पैटर्न-मिलान दृष्टिकोण का प्रयास कर सकते हैं। मैंने थोड़ी देर में F # का उपयोग नहीं किया है और मैं चीजों का परीक्षण नहीं कर सकता अब, लेकिन यह कुछ ऐसा होगा:

let rec curse sofar ls = 
    match ls with 
    | even :: odd :: tl -> curse (even :: sofar) tl 
    | even :: [] -> curse (even :: sofar) [] 
    | [] -> List.rev sofar 

curse [] [ 1; 2; 3; 4; 5 ] 

यह बार-बार भी ग्यारह लोगों को चुनता है ts। मुझे लगता है। हालांकि मैं शायद जोएल म्यूएलर के दृष्टिकोण का उपयोग करूंगा। अगर वहाँ एक सूचकांक आधारित filter समारोह मुझे याद नहीं है, लेकिन यह शायद का उपयोग करने के लिए आदर्श, या यदि वह पुस्तकालयों में मौजूद नहीं है बनाने के लिए किया जाएगा।

लेकिन सामान्य सूची में वास्तव में सूचकांक प्रकार चीजों के रूप में नहीं होती हैं। यही कारण है कि सरणी हैं। आप समझते हैं एल्गोरिथ्म की तरह इसकी भी तत्वों को निकाल होने एक सूची की आवश्यकता होगी क्या है, शायद यह संभव है कि कदम इस आवश्यकता से पहले में, तत्वों अप tuples में, बनती जा सकती है, इस तरह:

[ (1,2); (3,4) ] 

यही होगा यह तुच्छ even- "अनुक्रमित" तत्वों बाहर निकलने के लिए करते हैं:

thelist |> List.map fst // take first element from each tuple 

वहाँ विकल्प की एक किस्म है कि अगर इनपुट सूची तत्वों की एक भी नंबर है की गारंटी नहीं है।

0

फिर भी एक और विकल्प है, जो (मेरे गणना से) जोएल की तुलना में थोड़ी धीमी है, लेकिन यह कम :)

let removeEven list = 
    list 
    |> Seq.mapi (fun i x -> (i, x)) 
    |> Seq.choose (fun (i,x) -> if i % 2 = 0 then Some(x) else None) 
    |> List.ofSeq 
संबंधित मुद्दे