List 比较Haskel中的列表

List 比较Haskel中的列表,list,haskell,reduce,List,Haskell,Reduce,我必须定义一个名为zeros的函数,它接受两个列表的输入并返回一个布尔值,如果数字0在每个列表中出现的次数相同,则返回True,否则返回false 这是我家庭作业中的最后一个问题,我已经设法解决了这个问题,让它开始工作,但我想知道是否有人能找到减少代码量的方法,任何想法都值得赞赏。我的代码如下: x :: Int x = 0 instances::[Int]->Int instances [] = 0 instances (y:ys) | x==y = 1+(instances

我必须定义一个名为zeros的函数,它接受两个列表的输入并返回一个布尔值,如果数字0在每个列表中出现的次数相同,则返回True,否则返回false

这是我家庭作业中的最后一个问题,我已经设法解决了这个问题,让它开始工作,但我想知道是否有人能找到减少代码量的方法,任何想法都值得赞赏。我的代码如下:

x :: Int
x = 0 
instances::[Int]->Int
instances [] = 0
instances (y:ys)
    | x==y = 1+(instances ys)
    | otherwise = instances ys



zeros :: [Int] -> [Int] -> Bool
zeros [] [] = False
zeros x y
       | ((instances x) == (instances y)) = True
       | otherwise = False

您是否想过一次过滤每个列表,只得到零,然后比较列表的长度,看看它们是否相等

zeroCompare xs ys = cZeroes xs == cZeroes ys
  where
    cZeroes as = length $ filter (== 0) as

您是否想过一次过滤每个列表,只得到零,然后比较列表的长度,看看它们是否相等

zeroCompare xs ys = cZeroes xs == cZeroes ys
  where
    cZeroes as = length $ filter (== 0) as

由于这是一个家庭作业,在不透露太多的情况下,这里有一些提示

你知道列表的理解吗?在这种情况下,它们会很有用。例如,您可以将它们与
if
表达式组合,以执行以下操作:

*Main> let starS s = [if c == 's' then '*' else ' ' | c <- s]
*Main> starS "schooners"
"*       *"
这里有一个函数可以做同样的事情

lensMatch' xs ys = length xs == length ys
你可以看到它们是一样的;测试第一个:

*Main> lensMatch [1..4] [1..4]
True
*Main> lensMatch [1..4] [1..5]
False
*Main> lensMatch [] [1..5]
False
*Main> lensMatch [] []
True
以及测试第二个:

*Main> lensMatch' [1..4] [1..4]
True
*Main> lensMatch' [1..4] [1..5]
False
*Main> lensMatch' [] [1..5]
False
*Main> lensMatch' [] []
True

最后,我非常同意sblom的上述评论<代码>零[][]应为
!考虑以下语句:“对于集合s中的每个项目x,x>0”。如果set s为空,则该语句为真!这是真的,因为s中根本没有项目。在我看来,这似乎是类似的情况

不要透露太多,因为这是家庭作业,这里有一些提示

你知道列表的理解吗?在这种情况下,它们会很有用。例如,您可以将它们与
if
表达式组合,以执行以下操作:

*Main> let starS s = [if c == 's' then '*' else ' ' | c <- s]
*Main> starS "schooners"
"*       *"
这里有一个函数可以做同样的事情

lensMatch' xs ys = length xs == length ys
你可以看到它们是一样的;测试第一个:

*Main> lensMatch [1..4] [1..4]
True
*Main> lensMatch [1..4] [1..5]
False
*Main> lensMatch [] [1..5]
False
*Main> lensMatch [] []
True
以及测试第二个:

*Main> lensMatch' [1..4] [1..4]
True
*Main> lensMatch' [1..4] [1..5]
False
*Main> lensMatch' [] [1..5]
False
*Main> lensMatch' [] []
True

最后,我非常同意sblom的上述评论<代码>零[][]应为
!考虑以下语句:“对于集合s中的每个项目x,x>0”。如果set s为空,则该语句为真!这是真的,因为s中根本没有项目。在我看来,这似乎是类似的情况

我不敢相信还没有人建议使用。不是最短或最好的定义,而是最具教育意义的定义:

instances :: Eq a => a -> [a] -> Int
instances n = foldr incrementIfEqual 0
    where incrementIfEqual x subtotal
              | x == n = subtotal + 1
              | otherwise = subtotal

zeros :: Num a => [a] -> [a] -> Bool
zeros xs ys = instances 0 xs == instances 0 ys
虽然对于
实例的一个非常简短的定义
,我提出的基本上与Abizern相同:

instances :: Eq a => a -> [a] -> Int
instances x = length . filter (==x)

我不敢相信还没有人建议使用。不是最短或最好的定义,而是最具教育意义的定义:

instances :: Eq a => a -> [a] -> Int
instances n = foldr incrementIfEqual 0
    where incrementIfEqual x subtotal
              | x == n = subtotal + 1
              | otherwise = subtotal

zeros :: Num a => [a] -> [a] -> Bool
zeros xs ys = instances 0 xs == instances 0 ys
虽然对于
实例的一个非常简短的定义
,我提出的基本上与Abizern相同:

instances :: Eq a => a -> [a] -> Int
instances x = length . filter (==x)

代替
length
filter
,您可以获取谓词
p
的结果,将其转换为0或1,并对结果求和:

count p = sum . map (fromEnum.p)

--or

import Data.List
count p = foldl' (\x -> (x+).fromEnum.p) 0

在您的例子中,
p
当然是
(==0)
。使用Enum中的
Bool
转换为
Int
是一个非常有用的技巧。

代替
length
filter
,您可以获取谓词
p
的结果,将其转换为0或1,并对结果求和:

count p = sum . map (fromEnum.p)

--or

import Data.List
count p = foldl' (\x -> (x+).fromEnum.p) 0

在您的例子中,
p
当然是
(==0)
。使用
fromEnum
Bool
转换为
Int
是一个非常有用的技巧。

另一个想法是同时处理这两个列表,虽然有点长,但很容易理解:

zeros xs ys = cmp xs ys == 0 where
  cmp (0:xs) ys = cmp xs ys + 1
  cmp xs (0:ys) = cmp xs ys - 1
  cmp (_:xs) ys = cmp xs ys
  cmp xs (_:ys) = cmp xs ys
  cmp [] []     = 0

另一个想法是同时处理这两个列表,虽然有点长,但很容易理解:

zeros xs ys = cmp xs ys == 0 where
  cmp (0:xs) ys = cmp xs ys + 1
  cmp xs (0:ys) = cmp xs ys - 1
  cmp (_:xs) ys = cmp xs ys
  cmp xs (_:ys) = cmp xs ys
  cmp [] []     = 0

我将把这个问题分解为涉及辅助函数的小问题

以下是我将如何分解它:

  • 比较两个计数的主函数
  • 计数辅助函数
  • 首先:您需要一种方法来计算列表中零的数量。例如,如果在整数列表中搜索0的数目,我将执行以下操作:

    count :: [Int] -> Int
    count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
    
    第二:您需要一种方法来比较两个列表的计数。本质上,您需要一个函数,该函数将两个列表作为参数,计算每个列表的计数,然后根据结果返回布尔值。例如,如果每个列表都是整数列表,则与上面的计数示例相对应:

        equalZeroes :: [Int] -> [Int] -> Bool
        equalZeroes x y = (count x) == (count y)
    
    您还可以在equalZeroes函数中的where关键字下定义count,如下所示:

    equalZeroes :: [Int] -> [Int] -> Bool
    equalZeroes x y = (count x) == (count y)
        where
            count :: [Int] -> Int
            count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
    
    运行此代码时,按原样调用函数将返回所需的布尔值:

    equalZeroes [0,1,4,5,6] [1,4,5,0,0]
    -> False
    
     equalZeroes [0,1,4,5,6] [1,4,5,0]
     -> True
    

    我将把这个问题分解为涉及辅助函数的小问题

    以下是我将如何分解它:

  • 比较两个计数的主函数
  • 计数辅助函数
  • 首先:您需要一种方法来计算列表中零的数量。例如,如果在整数列表中搜索0的数目,我将执行以下操作:

    count :: [Int] -> Int
    count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
    
    第二:您需要一种方法来比较两个列表的计数。本质上,您需要一个函数,该函数将两个列表作为参数,计算每个列表的计数,然后根据结果返回布尔值。例如,如果每个列表都是整数列表,则与上面的计数示例相对应:

        equalZeroes :: [Int] -> [Int] -> Bool
        equalZeroes x y = (count x) == (count y)
    
    您还可以在equalZeroes函数中的where关键字下定义count,如下所示:

    equalZeroes :: [Int] -> [Int] -> Bool
    equalZeroes x y = (count x) == (count y)
        where
            count :: [Int] -> Int
            count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
    
    运行此代码时,按原样调用函数将返回所需的布尔值:

    equalZeroes [0,1,4,5,6] [1,4,5,0,0]
    -> False
    
     equalZeroes [0,1,4,5,6] [1,4,5,0]
     -> True
    

    在我看来,
    0[][]
    应该等于
    True
    ?至少它并没有比<代码>零(1)[] /代码>更虚假,你的代码会考虑<代码>真< /代码>。我不确定你是否需要处理这个问题,因为如果列表是空的,那么它们将根本不包含零,因此这将是错误的。我很难说服自己“无零”和“零零”不是一回事。例如,