2013-11-26 3 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

I предположим, что вы не хотите просто вызывать ['List. max'] (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 # участвовал в ALOT рекурсии, спасибо за этот пример очень полезный. – 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 
Смежные вопросы