【问题标题】:haskell - Specifying # of conditions that are truehaskell - 指定 # 个条件为真
【发布时间】:2012-09-28 06:05:59
【问题描述】:

如果我有 4 个布尔条件,并且我想说如果其中至少 3 个为真,那么 __,这可以在 Haskell 中实现吗?

或者我必须经历每个排列吗? (即 1.True、2.True、3.True、4.False 和 1.False、2.True、3.True、4.True 等)

谢谢!

【问题讨论】:

    标签: list haskell boolean conditional-statements


    【解决方案1】:
    atleast :: Int -> [Bool] -> Bool
    atleast n bools = length tn == n
      where  tn = take n . filter id $ bools
    

    除非我错过了什么,否则应该懒惰地工作。

    【讨论】:

      【解决方案2】:

      如果您希望它在找到 N 个数字后停止检查列表,您可以使用惰性自然数进行计数。

      import Data.List
      import Data.Number.Natural
      
      atLeast :: Int -> [Bool] -> Bool
      atLeast n = (>= (fromIntegral n :: Natural)) . genericLength . filter id
      

      【讨论】:

        【解决方案3】:

        这不是最美丽的方式,但你可能会发现

        atLeast :: Int -> [Bool] -> Bool
        atLeast n bools = length (filter (==True) bools) >= n
        

        最容易理解。 filter 只保留列表中满足您给它的规则的东西。在这种情况下,规则是答案必须是True。接下来,length 计算剩余的数量。

        (规则是一个函数a -> Bool,其中a 是列表中元素的类型)。

        【讨论】:

        • 是的,就像我说的那样,不是最漂亮的方式,但也许很容易理解。在这一点上,我已经对 Ptharien's Flame 投了赞成票。请考虑这样做。
        • 这实际上是我认为写==True 的唯一地方,所以我不会和你争论。
        【解决方案4】:

        此解决方案与目前提供的其他解决方案的不同之处在于它会短路(即,在找到nBools 后停止)。所以它可以在一些无限列表上运行(只有那些最终会评估为 True 的列表),并且不一定会强制评估列表中的每个元素(由于懒惰)。

        atLeast :: Int -> [Bool] -> Bool
        atLeast 0 _          = True
        atLeast _ []         = False
        atLeast n (True:bs)  = atLeast (n - 1) bs
        atLeast n (False:bs) = atLeast n bs
        

        【讨论】:

          【解决方案5】:
          requireAtLeast :: Int -> [Bool] -> Bool
          requireAtLeast n = (>= n) . length . filter id
          

          如果您更喜欢极端有针对性或无意义的形式,分别是:

          requireAtLeast threshold predicates = length (filter (\predicate -> predicate) predicates) >= threshold
          
          requireAtLeast = (. length . filter id) . (<=)
          

          【讨论】:

          • 喜欢使用filter id(filter (\predicate -&gt; predicate) predicates) 让我发笑。
          【解决方案6】:
          atLeast3 :: Bool -> Bool -> Bool -> Bool -> Bool
          atLeast3 b1 b2 b3 b4 = sum (map fromEnum [b1, b2, b3, b4]) >= 3
          

          【讨论】:

          • 这种情况下可能问题不大,但是如果[b1,b2...bn]这个列表很大怎么办,有没有一种懒惰的比较方式不需要遍历整个列表呢?
          • @MagnusKronqvist,是的,请参阅 bisserlis、augustss 或 solrize 的回答。
          【解决方案7】:

          每个排列?当然不是。。你可以数数条件为真。

          【讨论】:

          • 是的,当你数到 3 时,你就可以停止计数了。
          猜你喜欢
          • 2013-08-25
          • 2016-11-30
          • 1970-01-01
          • 2011-04-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-02-14
          相关资源
          最近更新 更多