【问题标题】:Improve overly complex haskell list mapping?改进过于复杂的haskell 列表映射?
【发布时间】:2016-09-17 14:23:39
【问题描述】:

我有两个执行以下操作的函数:

获取两个 Ints 列表(list1,list2)。

取第一个列表的平均值,取一个范围值(r)。

在list2上映射,检查每个元素是否在范围内,如果超出范围则返回0。

将返回为 0 的任何 list2 元素转换为 False,将其他值转换为 True。

检查 list2 是否包含任何 False 值。

代码:

checkList :: Int -> Int -> Int -> Int --Check if element is within range
checkList element ave r
   | element >= (ave + (ave + r)) = 0
   | element <= (ave - (ave + r)) = 0
   | otherwise = e

mainFunc :: [Int] -> [Int] -> (Int -> Int -> Int -> Int) -> Bool
mainFunc list1 list2 checkL = elem (False) resultIntToBool --Check for any False elements
   where
      resultIntToBool = map (\element -> if element == 0 then False else True) result --Convert elements to bools
      result = map (\element -> checkL element ave r) list2 --Pass each element to checkL
      ave = sum list1 `div` length list1 --Calculate average
      r = ave + 30 --Create range value 

我怎样才能使这段代码不那么冗长和更易读?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    我不确定我是否正确理解了你的问题,但我认为你要求的是有一个函数可以检查list2 的所有元素是否在avg - ravg + r 之间,其中avglist1r 的平均值是某个数字。

    如果正确,我将在您的代码中进行以下更改:

    1. 我会将checkList 移动到mainFunc 中。这允许您直接引用在where 子句中定义的符号,这可以使代码在这种情况下更具可读性。
    2. 我会让checkList 返回一个布尔值而不是一个整数,因为您使用整数时就好像它是一个布尔值一样。这还可以让您大大简化函数的定义,现在可以使用单个布尔表达式来定义(不需要多个情况)。
    3. 我会将checkList 重命名为更具描述性的名称,例如checkInRange
    4. 最后,我将使用 Prelude (http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:all) 中的函数 [all] 来检查列表的所有元素是否满足某个属性。

    把它们放在一起:

    mainFunc :: [Int] -> [Int] -> Bool
    mainFunc list1 list2 = all checkInRange list2
      where
        checkInRange element = ave - r <= element && element <= ave + r
        ave = sum list1 `div` length list1 --Calculate average
        r = 30 --Create range value 
    

    【讨论】:

      猜你喜欢
      • 2012-10-16
      • 2020-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-27
      • 1970-01-01
      相关资源
      最近更新 更多