2013-11-26 18 views
3

我想要一個函數,它將一個整數列表作爲參數,並比較每個值並返回最大值。在C#中,我只需遍歷列表中的每個值,將最大值保存到一個變量並返回它,我希望F#的工作方式類似,但語法對我來說有點不友好,這裏是我的代碼的樣子。另外,max2是一個比較2個值並返回最大值的函數。比較功能中的循環內的值

let max_list list = 
    let a = 0 : int 
    match list with 
    | head :: tail -> (for i in list do a = max2 i a) a 
    | [] -> failwith "sry";; 
+1

我假設你不想簡單地調用['List。最大'](http://msdn.microsoft.com/en-us/library/vstudio/ee370242.aspx),對不對? – svick

+0

這是正確的 – Jacco

回答

12

你可以使用mutable變量和使用for循環,就像在C#編寫的代碼。但是,如果您正在學習F#和功能概念,那麼使用遞歸是個好主意。

在這種情況下,遞歸函數稍微長一些,但它演示了包括模式匹配在內的關鍵概念 - 因此學習這些技巧在編寫更復雜的F#代碼時會很有用。

關鍵的想法是編寫一個函數,該函數採用迄今爲止發現的最大值並遞歸調用自身,直到它到達列表的末尾。

let max_list list = 
    // Inner recursive function that takes the largest value found so far 
    // and a list to be processed (if it is empty, it returns 'maxSoFar') 
    let rec loop maxSoFar list = 
    match list with 
    // If the head value is greater than what we found so far, use it as new greater 
    | head::tail when head > maxSoFar -> loop head tail 
    // If the head is smaller, use the previous maxSoFar value 
    | _::tail -> loop maxSoFar tail 
    // At the end, just return the largest value found so far 
    | [] -> maxSoFar 
    // Start with head as the greatest and tail as the rest to be processed 
    // (fails for empty list - but you could match here to give better error) 
    loop (List.head list) (List.tail list) 

作爲最後一點,這會很慢,因爲它使用通用比較(通過接口)。您可以使用let inline max_list list = (...)使功能更快。這樣,代碼將使用本機比較指令時,與基本類型如int(這是一個非常特殊的情況 - 問題只發生在通用比較)

+0

總是聽說F#涉及很多遞歸,謝謝這個例子非常有用。 – Jacco

+0

在實踐中,你不需要經常遞歸*,因爲你通常可以編寫現有的函數 - 在這種情況下,你可以使用'List.max',並且在大多數情況下,有一些現有的函數。但是如果你需要一些不存在的東西,那麼知道遞歸是很好的。 –

3

也知道你可以寫一個很好的單線使用減少:

let max_list list = List.reduce (fun max x -> if x > max then x else max) 
0

如果你的目的是爲了能夠找到列表中的項目的最高值,其中物品的價值是由函數MAX2找到,那麼這種方法的工作原理:

let findMax list = 
    list 
    |> List.map (fun i -> i, max2 i) 
    |> List.maxBy snd 
    |> fst