Поиск по списку - PullRequest
       15

Поиск по списку

0 голосов
/ 09 апреля 2011

Я пытался определить функцию, которая, учитывая список целых чисел и целое число n, возвращает логическое значение, указывающее, встречается ли n ровно один раз в списке.

У меня есть это, но оно не работает, и я не могу понять это

once :: [a] -> (a -> Bool) -> Bool 
filter _ [] = []  
filter p (x:xs)   
    | p x       = x : filter p xs  
    | otherwise = filter p xs 

An example of what I want would be:
Main>  once [2,3,2,4] 2
False
Main> once [1..100] 2
True

Ответы [ 4 ]

6 голосов
/ 10 апреля 2011

Поскольку я думал, что мое прежнее решение было некрасивым, я спросил у другого форума и получил ответ:

once :: Eq a => a -> [a] -> Bool
once x = (== [x]) . filter (== x)

Я думаю, что вы не можете написать эту функцию намного лучше,и в отличие от принятого ответа он ленивый.

2 голосов
/ 09 апреля 2011
once :: (Eq a) => [a] -> a -> Bool
once xs x = (== 1) $ length $ filter (== x) xs
2 голосов
/ 09 апреля 2011

Ну, вы можете отфильтровать список, а затем посмотреть, сколько элементов в результирующем фильтре, верно?

Для начала:

 > filter (== 2) [1,2,3,4,5]
 [2]

 > filter (== 2) [1,2,3,4,5,2,2]
 [2,2,2]

И свернуть список внизк значению Bool, вот пример, где мы проверяем, есть ли в списке три элемента, возвращая Bool:

 > isThree (a:b:c:[]) = True
 > isThree _          = False 

Так что составление таких функций - просто короткий вопрос:

 > isThree . filter (==2)

или ваш вариант (например, поиск по спискам длиной 1).

0 голосов
/ 09 апреля 2011

Вот другая версия:

once x = not . (\xs -> null xs || x `elem` tail xs) . dropWhile (/= x)

--lambda hater version
import Control.Applicative
once x = not . ((||) <$> null <*> (elem x).tail) . dropWhile (/= x)

Конечно, он не может иметь дело с бесконечными списками, которые содержат ноль или один x, но, по крайней мере, он заканчивается в случае более чем одного появления x.

...