Ответ 1
Используя maximumBy
, on
и compare
вы можете написать выражение следующим образом:
import Data.List (maximumBy)
import Data.Function (on)
maximumBy (compare `on` length) ["one", "two", "three", "four", "five"]
Я не могу понять свой ум в функциональном мышлении, чтобы решить эту проблему простым способом, который также мог бы работать для очень длинных списков. Если у вас есть список, например:
["one", "two", "three", "four", "five"]
Я могу сказать, что длина самого длинного слова довольно просто:
maximum $ map length ["one", "two", "three", "four", "five"]
Как мне изменить предыдущий оператор, чтобы вернуть строку три?
Используя maximumBy
, on
и compare
вы можете написать выражение следующим образом:
import Data.List (maximumBy)
import Data.Function (on)
maximumBy (compare `on` length) ["one", "two", "three", "four", "five"]
btw, если у вас не было готового к использованию maximumBy
, простым способом было бы украшение-сортировка-undecorate pattern/idiom (работающая на других языках, таких как Python или Scheme):
snd $ maximum $ map (\x -> (length x, x)) ["one", "two", "three", "four", "five"]
Но так как исходная полезная нагрузка также является частью ключа сортировки, результат не всегда является первым вложением самого длинного слова (в этом случае было только одно слово с самой длинной длиной)
Эта функция (или даже библиотека) не кажется хорошо известной, но у Haskell на самом деле есть модуль с именем Data.Ord
, который содержит функцию comparing
, которая почти похожа на использование Data.Function.on
в верхнем ответе, за исключением код заканчивается более идиоматичным.
g>import Data.Ord
g>import Data.List
g>let getLongestElement = maximumBy (comparing length)
getLongestElement :: [[a]] -> [a]
g>getLongestElement ["one", "two", "three", "four", "five"]
"three"
Код практически читается как английский. "Получите максимум, сравнивая длину".
maximumBy
(\x -> (x, length x))
, fst
и snd
в простой композиции делают трюк.
Чтобы вычислить length a
, вам нужно пройти весь список a
. В этом конкретном случае использования вас беспокоит только самое длинное слово, а не точно, как долго они длится, поэтому вы можете написать функцию, которая только заходит так далеко, насколько это необходимо в каждом списке, чтобы определить, какой из них самый длинный. Это может сэкономить вам некоторую обработку:
module Main where
main = putStrLn $ longestWordInList ["one", "two", "three", "four"]
longestWordInList = go ""
where go result [] = result
go result (x:xs) = let result' = longestWord result x in
result' `seq` go result' xs
longestWord a b = go a b a b
where go a _ _ [] = a
go _ b [] _ = b
go a b (_:as) (_:bs) = go a b as bs
foldl (\accmax xs -> if length accmax < length xs then xs else accmax) [] ["one", "two", "three", "four", "five"]