改进过于复杂的haskell列表映射?

时间:2016-09-17 14:23:40

标签: haskell

我有两个执行以下功能的功能:

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

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

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

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

Check is 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 

如何让这段代码更简洁,更易读?

1 个答案:

答案 0 :(得分:3)

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

如果这是正确的,这就是我在代码中要改变的内容:

  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]来检查列表的所有元素是否满足属性。
  5. 全部放在一起:

    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