2015-06-09 11 views
6

Próbuję napisać funkcję, która zwraca dłuższe z dwóch ciągów. Do tej pory jest to, co mam:Elegancki sposób zwracania dłuższego z dwóch ciągów znaków

maxString :: String -> String -> String 
maxString a b 
    | (length a) > (length b) = a 
    | otherwise = b 

To działa, ale zastanawiam się, czy istnieje bardziej elegancki sposób to napisać. Uwaga: te dwa argumenty nie mogą znajdować się na liście. Muszą być oddzielne argumenty, aby umożliwić curry.

Myśli?

+1

uważaj na nieskończone listy! – karakfa

Odpowiedz

6

Jest to najbardziej zwięzły sposób na jego napisanie. Jednak poniższa wersja zakończy się nawet wtedy, gdy jedna lista będzie nieskończona (O (min (a, b)) zamiast O (a + b)).

Nie ma też prawdziwego powodu, aby ograniczać funkcję do samych ciągów, gdy ma to sens w przypadku dowolnych list.

8

Można użyć istniejących obiektów Haskell w Data.Ord i Data.Function i uzyskać jedno-liner następująco:

maxString' x y = maximumBy (compare `on` length) [x, y] 

Kod:

import Data.Ord 
import Data.Function 
import Data.List 

maxString' x y = maximumBy (compare `on` length) [x, y] 

*Main> maxString' "ab" "c" 
"ab" 

- EDIT -

Jako @ DavidYoung wskazał,

compare `on` length 

Powyższe można również napisać w krótszej formie: comparing length

+2

Możesz również napisać '' porównaj 'on' length'' jako' porównanie długości'. –

+0

@DavidYoung Dzięki. Zgadza się. – tinlyx

9

Do tej pory wszystkie odpowiedzi, z wyjątkiem Tejinga, w pełni przekraczają oba argumenty. Ten przechodzi tylko do końca krótszego.

longest a b = l' a b where 
    l' _ [] = a 
    l' [] _ = b 
    l' (_:ar) (_:br) = l' ar br 
+0

To jest interesujące. sława – dopatraman

8

Zagrałem z tym trochę. Chciałem, aby był on jednolinijkowy, a także miał złożoność O(min(n,m)). (tzn. działa nawet z nieskończonymi listami)

maxList :: [a] -> [a] -> [a] 
maxList s s' = if s == zipWith const s s' then s' else s 
Powiązane problemy