对于作业,我被要求使用列表理解重写以下函数。此函数接受整数列表和整数数字a
,并返回列表中包含数字a
的整数数。
e.g。
count [102,41,256] 2
应该返回2
count [98,4,376] 2
应该返回0
这就是我对非列表理解函数所具有的:
split :: Int -> [Int]
split 0 = []
split x = split (div x 10) ++ [rem x 10]
checkDigits :: [Int] -> Int -> Int
checkDigits [] y = 0
checkDigits (x:xs) y
| x == y = 1 + (checkDigits xs y)
| otherwise = checkDigits xs y
count :: [Int] -> Int -> Int
count [] a = 0
count (x:xs) a
| (checkDigits (split x) a) > 0 = (checkDigits (split x) a) + (count xs a)
| otherwise = count xs a
Split将接受一个整数并返回列表中的整数
split 321 will return: [3,2,1]
checkDigits
计算一个数字出现在整数中的次数(这是为了解决count [22] 2
返回0
时应返回的错误2
)
e.g. the digit '2' appears 4 times in the list [2,65,42,22]
最后在计数中,我们使用checkDigits
检查x
中的任何数字是否等于a
,如果此数字大于0(1或更多等于a )然后添加找到的位数并再次调用。
我是列表理解的新手,如果列表中的数字等于a
,我只能设法让它工作:
countD :: [Int] -> Int -> Int
countD intL a = length [y | y <- intL, y == a]
此处countD [2,3,4,22] 2
返回1
我如何更改我的内容,以便它返回3
(因为有2
个列表)。
答案 0 :(得分:5)
我能做的最好。 如果有人向我展示如何将整数,我会感激。2
数字作为参数传递而不是硬编码
感谢Erik的回答。
countDigits :: [Int] -> Int -> Int
countDigits xs d = sum [1 | n <- (concat . map show) xs, n == d']
where d':[] = show d
答案 1 :(得分:3)
在checkDigits
中使用split
和countD
。这是计算包含数字的整数的数量(在您的示例中为两个):
countD intL a = length [y | y <- intL, (checkDigits (split y) a) > 0]
以下是数字出现的总次数(在您的示例中为三个):
countD intL a = sum [checkDigits (split y) a | y <- intL]
答案 2 :(得分:3)
你的问题对count
函数应该准确做什么不明确。一开始你说
列表中包含数字
的整数数
而后来你说
count [22] 2
/.../应该返回2
不 2
中包含数字[22]
的整数数 - 该列表中只有一个整数,所以你应该返回1,不管这个整数包含数字2
两次的事实。
因此,我已经为下面两种可能性提供了解决方案。
对于第一种可能性,这个解决方案是我能想到的最短的解决方案:
-- these are optional
type Digit = Int
type Number = Int
type Count = Int
count :: [Number] -> Digit -> Count
count xs d = sum [count' x | x <- xs] -- same as `sum $ map count' xs`
where count' x = if d' `elem` show x then 1 else 0
d':[] = show d
但是,如果第二种可能性确实正确并且count [22] 2
应该返回2
,那么相应地更改count'
辅助函数:
count :: [Number] -> Digit -> Count
count xs d = sum [count' x | x <- xs]
where count' i = length $ filter (== d') (show i)
d':[] = show d