2011-01-16 39 views
19

No entiendo mi mentalidad funcional para resolver este problema de una manera simple que también podría funcionar para listas muy largas. Si usted tiene una lista como:¿Cómo encontrar la palabra más larga en la lista?

["one", "two", "three", "four", "five"] 

puedo decir lo que la longitud de la palabra más larga es bastante simple con:

maximum $ map length ["one", "two", "three", "four", "five"] 

¿Cómo puedo modificar la declaración anterior a devolver la cadena tres ?

+0

@ Marcos Byers Volver la primera aparición de la palabra más larga. –

Respuesta

37

Usando maximumBy, on y compare puede escribir la expresión como esta:

import Data.List (maximumBy) 
import Data.Function (on) 

maximumBy (compare `on` length) ["one", "two", "three", "four", "five"] 
+6

'compare \' en \ 'length' es' comparando length' donde 'comparing' es de' Data.Ord'. – Peaker

+0

Muy elegante. Buena solución. –

3

maximumBy(\x -> (x, length x)), fst, y snd en una composición sencilla hacer el truco.

12

Por cierto, si uno no tenía lista para su uso maximumBy, una forma sencilla sería el patrón de decorar-tipo-Undecorate/idioma (que funciona en otros lenguajes como Python o Esquema también):

snd $ maximum $ map (\x -> (length x, x)) ["one", "two", "three", "four", "five"] 

Pero ya que la carga útil original es también parte de la clave de ordenación, el resultado no siempre es la primera aparición de la palabra más larga (en este caso solo había una palabra con la longitud más larga)

+3

Incluso con 'maximumBy', esto es útil. La función 'maximumBy' recalculará la longitud (o la función de comparación que se use) del token actual más largo en cada comparación, mientras que decorate-sort-undecorate solo calcula la longitud una vez. Esta versión es notablemente más eficiente incluso con entradas de tamaño modesto. Por supuesto, si usa listas de cualquier longitud, probablemente no deba usar listas. –

+0

@John si solo está haciendo una pasada sobre una secuencia de datos, una lista de cualquier longitud está perfectamente bien. Ahora cadenas por otro lado ... – sclv

+0

@John, gracias por señalar el problema de 'máximo (Por)' reevaluación de 'max', del cual no era consciente y me sorprendió un poco (implementando' máximo' simplemente con 'foldl1 max' es sin dudas elegante, sin embargo) – hvr

8

Esta función (o incluso biblioteca) no parece ser conocida, pero Haskell en realidad tiene un módulo llamado Data.Ord que contiene la función comparing que es casi como usar Data.Function.on en la respuesta superior, excepto que el código termina siendo más idiomático.

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" 

El código prácticamente se lee como en inglés. "Obtener el máximo al comparar la longitud".

+0

Otros no están de acuerdo, y piensan que "comparar" es un caso especial tonto. No me importa, pero escuché a gente experimentada quejarse de eso. – dfeuer

1

Para calcular length a, debe recorrer toda la lista a. En este caso de uso particular, solo está preocupado por la palabra más larga, y no exactamente cuánto tiempo son, por lo que puede escribir una función que solo llegue hasta donde sea necesario en cada lista para determinar cuál es la más larga. Esto le puede ahorrar algo de procesamiento:

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 
+0

No necesita tantos argumentos para 'go'. Simplemente use diferentes nombres y refiérase a los que están en el alcance externo. 'longestWord a b = ir a b donde ir a '_ = a ...' – dfeuer

0
foldl (\accmax xs -> if length accmax < length xs then xs else accmax) [] ["one", "two", "three", "four", "five"] 
Cuestiones relacionadas