通过列表搜索

问题描述:

我一直在试图定义一个函数,给定一个整数和一个整数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 

once :: (Eq a) => [a] -> a -> Bool 
once xs x = (== 1) $ length $ filter (== x) xs 
+0

感谢您的任何想法如何处理无限的列表? – John 2011-04-08 23:16:00

+0

约翰,你需要在列表中匹配它的长度,而不是像下面的答案那样取长度。 – 2011-04-09 02:23:17

+1

我不认为在一般情况下可以处理无限列表。如何知道确定性程序停止在'repeat 2'中寻找'1'? – acfoltzer 2011-04-09 02:34:06

好了,你可以过滤列表,然后看看有多少元素在得到的滤波器,对不对?

为了让你开始:

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

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

和你的列表中上下折叠成一个布尔值,在这里,在这里我们测试如果列表中有三个元素的例子,返回一个布尔值:

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

所以它是构成这种功能只有很短的事情:

> isThree . filter (==2) 

或您的变种(如匹配对于长度为1的列表)。

+0

我知道,但我只是不知道如何输出到布尔值而不是列出匹配的内容。 – John 2011-04-08 21:34:32

+0

比较列表的长度与1? – 2011-04-08 21:48:59

+0

Once :: [a] - > a - > Bool filter(k)[a] If 1 John 2011-04-08 21:54:39

这里是另一个版本:

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的出现了多次的情况下终止。

,因为我以为我以前的解决方案是丑陋的,我问another forum和得到这个作为答案:

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

我认为你不能写一个函数更漂亮,并在对比接受的答案是懒。

+1

+1用于终止第二次出现的x,而不是遍历整个列表(“长度”)。 – Nefrubyr 2011-04-11 10:31:38

+0

Upvoted。教我新的东西。 – 2011-04-11 15:17:24

+0

* 1,但是如果确实存在第二个x并且它不是最后一个元素,则它只是更懒。说实话,应用这个函数的人必须假定整个列表都会被评估。 – Ingo 2011-04-12 16:59:57