【问题标题】:function that satisfies the majority of elements in haskell满足haskell中大多数元素的函数
【发布时间】:2012-05-21 21:10:32
【问题描述】:

我需要编写一个代码,如果函数满足列表的大部分元素,则返回 True,而其中的 false 不满足。 例如:moreThan odd [1,2,3] 是 True,但 moreThan odd [1,2,3,4] 是 False。 这是我的代码:

moreThan funkt xs
   = let
      control funkt n (x : xs)
         = control (if .?. then n + 1 else n) xs
      contol funkt _
         = False
   in
   control funtk 0 xs

有人可以说我如何控制它以及我应该在.?. 中写什么 谢谢!

【问题讨论】:

  • moreThan = ((\(lTrue,lFalse) -> length lTrue > length lFalse).) . partition 会更惯用一些。
  • 好吧,如果你只使用 let 而不是随机无意义的 lambda,那会更习惯。
  • 嗯,首先我要问:这是作业吗?如果是这样,则应使用 [homework] 标记。
  • 不,我有一个基本的 Haskell 考试,我正在努力准备它。所以,我不知道如何解决这个练习,如果你能告诉我如何解决,我会很高兴。
  • @leftaroundabout: 更性感的(>>> uncurry (>) <<< length *** length) <<< partition 怎么样? :D

标签: list function haskell


【解决方案1】:

您编写的函数将为所有参数返回False,因为当列表结束时您总是返回False。

您编写的函数需要跟踪两个变量:处理的元素数和谓词为真的元素数。由于这段代码可能是家庭作业,我给你一个构造,你可以用它来编写函数。在-- ??? 处填写您自己的代码。

moreThan :: (a -> Bool) -> [a] -> Bool
moreThan pred = go 0 0 where
  -- procd: number of elements processed
  -- holds: number of elements for which pred holds
  go procd holds (x:xs) = go procd' holds' xs where
     procd' = -- ???
     holds' = -- ???
  go procd holds []     = -- ???

如果您需要更多提示,请随时发表评论。


编写此函数的一种更惯用的方法是使用折叠:

moreThan pred = finalize . foldr go (0,0) where
  -- process one element of the input, produce another tuple
  go (procd,holds) x = -- ???
  -- produce a boolean value from the result-tuple
  finalize (procd,holds) = -- ???

【讨论】:

  • foldr 是解决此类问题的错误选择。而且您只需要跟踪一件事,即计数差异。 (> 0) . foldl' (\n x -> if p x then n+1 else n-1) 0 是我觉得惯用的。
  • @Daniel Fischer 关于 foldr uniodeomatic 的方式是什么?单计数器的想法很好。
  • 我不是说foldr 是单一的(尤其是不是一般的),它只是手头问题的错误习语。更新函数在两个参数中都是严格的,结果与处理列表元素的顺序无关,foldl' 的一个明显例子。
【解决方案2】:

了解你的库!

import Data.List(partition)
import Data.Function(on)

moreThan f = (uncurry $ on (>) length) . partition f

如果不允许使用分区,就自己写吧:

part f xs = (filter f xs, filter (not.f) xs)

或者采用数字方式:

moreThan f xs = 2*s > length xs where s = sum $ map (fromEnum.f) xs

【讨论】:

    【解决方案3】:

    也许不是最有效的解决方案,但肯定是一个非常明确的解决方案,如下:

    moreThan :: (a -> Bool) -> [a] -> Bool
    moreThan f xs = length ts > length fs where
        ts = filter id bools
        fs = filter not bools
        bools = map f xs
    

    【讨论】:

      【解决方案4】:
      majority :: (a -> Bool) -> [a] -> Bool
      majority p = (0 <) . sum . map (\x -> if pred x then 1 else -1)
      

      这是对列表元素的映射(如果 pred x then 1 else -1),然后对列表元素求和并查看结果是否> 0。

      【讨论】:

        【解决方案5】:

        我希望这是有效的(只遍历列表一次)但仍然相当清晰。

        majority :: (a -> Bool) -> [a] -> Bool
        majority pred = g . sum . map f
          where f x | pred x    = 1
                    | otherwise = -1
                g y = 0 < y
        

        【讨论】:

          猜你喜欢
          • 2017-02-18
          • 1970-01-01
          • 2018-07-26
          • 2019-06-12
          • 1970-01-01
          • 2011-04-16
          • 2017-08-09
          • 2019-07-06
          相关资源
          最近更新 更多