首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检查列表其余部分中的元素(lx)

检查列表其余部分中的元素(lx)
EN

Stack Overflow用户
提问于 2015-03-26 15:18:54
回答 3查看 149关注 0票数 1

最近,我找到了Haskell,我在输入代码时遇到了困难,无法查看元素是否在列表(x:lx)的其余部分--在本例中是lx。我的代码:

代码语言:javascript
复制
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y 
 | (x==y) && (`lx` == y) = False
 | otherwise = True

现在的方法是检查第一个元素(x==y),但我不知道如何检查y元素是否存在于lx中。实际上,我要做的是找出lx列表中的数字y是否包含0或1次,然后返回True,否则返回False

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-03-26 15:40:55

您可以使用elem函数来完成这一任务:

代码语言:javascript
复制
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
                    | otherwise = not $ elem y lx

最好首先检查元素x是否为,而不是是否等于y。如果是这样的话,只需调用递归部分atmostonce lx y:这样就可以在列表中进一步搜索。

对于x == y,( otherwise情况),您需要检查lx中是否有另一个元素(列表的其余部分),该元素等于x。如果是这样,则需要返回False,因为在这种情况下,列表中有多个实例。否则您将返回True

此外,您还可以进一步概括您的功能:

代码语言:javascript
复制
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
                    | otherwise = not $ elem y lx

Eq是一个类型类型,它意味着在a上定义了函数==/=。因此,您可以调用它们,而不管真正的a类型(IntString,不管怎样)。

最后,在第一种情况下,您可以使用下划线(_),这意味着您不关心值(尽管在本例中它并不重要)。您也许可以更改这些情况的顺序,因为它们是断续的,这使得函数在语法上是总计的。

代码语言:javascript
复制
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce (x:lx) y | x /= y = atmostonce lx y
                    | otherwise = not $ elem y lx
atmostonce _ _ = True
票数 1
EN

Stack Overflow用户

发布于 2015-03-26 15:43:31

您可以为此使用几个实现,其中一个避免将length应用于潜在无限列表的实现是

代码语言:javascript
复制
atmostonce xs y
    = (<= 1)
    $ length
    $ take 2
    $ filter (== y) xs

这将从xs中删除不等于y的所有元素,然后取其中最多2个元素(take 2 [1] == [1]take 2 [] == []),计算长度(在这里使用是安全的,因为我们知道take 2不会返回无限列表),然后检查它是否不超过1。或者您可以使用直接递归来解决这个问题,但是最好使用工作模式:

代码语言:javascript
复制
atmostonce = go 0
    where
        go 2 _      _ = False
        go n []     _ = n <= 1
        go n (x:xs) y =
            if x == y
                then go (n + 1) xs y
                else go n xs y

n <= 1子句可以被True替换,但理想情况下,它将在n == 2一次短路,n不应该是0、1或2以外的任何东西。然而,对于您的实现,我相信您正在寻找elem函数:

代码语言:javascript
复制
elem :: Eq a => a -> [a] -> Bool

atmostonce [] y = True
atmostonce (x:ls) y
    | (x == y) && (y `elem` ls) = False
    | otherwise = True

但是这不会返回您想要的值,因为atmostonce [1, 2, 2, 2] 2将返回True。相反,如果x /= y,则需要对列表的其余部分进行递归处理。

代码语言:javascript
复制
atmostonce (x:ls) y
    | (x == y) && (y `elem` ls) = False
    | otherwise = atmostonce ls y
票数 2
EN

Stack Overflow用户

发布于 2015-03-26 16:05:07

现有的答案是好的,但是您可以使用dropWhile来完成当前通过手动递归完成的部分:

代码语言:javascript
复制
atMostOnce xs y =
    let afterFirstY = drop 1 $ dropWhile (/= y) xs
    in y `notElem` afterFirstY
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29282281

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档