Сравнение значений в цикле внутри функции
Я хочу сделать функцию, которая принимает список целых чисел в качестве аргумента, сравнивает каждое значение и возвращает наибольшее значение. В 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";;
3 ответа
Вы могли бы использовать 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
(это действительно особый случай - проблема действительно возникает только при общем сравнении)
Также знайте, что вы можете написать хороший однострочный текст, используя Reduce:
let max_list list = List.reduce (fun max x -> if x > max then x else max)
Если ваше намерение состоит в том, чтобы найти максимальное значение элементов в списке, где значение элементов найдено функцией max2, тогда этот подход работает:
let findMax list =
list
|> List.map (fun i -> i, max2 i)
|> List.maxBy snd
|> fst