我刚刚开始学习Haskell(我试图制作一个策划者解决方案)。
我必须计算列表中一种颜色出现在另一个列表中的次数:
reaction [Green, Purple, Green, Green] [Purple, Green, Blue, Yellow] 0
必须给我结果" 2",因为" Green"从列表1开始,在列表2中出现1次,对于"紫色"同样如此。所以我写了一小段代码:
reaction [] ys n = n
reaction (x:xs) ys n = foldr (\y _ -> if x == y then reaction (filter' x xs) ys n + 1 else reaction xs ys n + 0) n ys
filter' c xs = filter(\x -> x /= c) xs
它从列表1中获取头部X并将其与列表2中的每个元素进行比较,如果它相同,它将过滤列表1中与X相对应的所有值(因此它不会计算任何值重复)并将+ 1添加到" N"。然而它给了我结果" 1",我真的无法找出原因......我希望有人能帮助我! 史蒂芬
答案 0 :(得分:1)
首先,filter'
只是filter (/= x)
。
根据您对问题的描述,更清晰的方式(至少最初)是
reaction [] ys n = n
reaction (x : xs) ys n | x `elem` ys = reaction (filter (/= x) xs) ys (n+1)
| otherwise = reaction xs ys n
这对我来说似乎不是一个简单的折叠,因为你迭代的列表(xs
)会随着你的迭代而改变。
答案 1 :(得分:1)
在你的代码中,你丢弃传递给foldr
的函数的第二个参数( accumulator ):
foldr (\y _ -> ...
我想不出foldr
的用例,你想要那样做。
你的问题似乎源于对foldr
的误解。你确定你明白这个功能是做什么的吗?如果您有任何疑问,请阅读this section of the Wikipedia page on folds;你应该找到解释正确折叠特别有启发性的图表。
如果我正确理解你想做什么,下面的方法应该可以做到:
import Data.List
data Color = Blue | Green | Purple | Yellow
deriving Eq
reaction :: Eq a => [a] -> [a] -> Int -> Int
reaction xs ys n = foldr (\x acc -> length (filter (== x) ys) + acc) n $ nub xs
有关信息,nub
函数采用列表并返回通过从中删除所有重复元素而形成的列表;它由Data.List
module导出。
λ> reaction [Green, Purple, Green, Green] [Purple, Green, Blue, Yellow] 0
2