基本上,我有这个练习:回顾上周的StudentMark类型同义词。编写一个递归函数:
0{"sid":"UeC7GEdBUWNM2Wm9AAAF","upgrades":[],"pingInterval":25000,"pingTimeout":5000}
给出特定学生的分数列表;例如:
listMarks :: String -> [StudentMark] -> [Int]
这是我编写函数的方式:
listMarks "Joe" [("Joe", 45), ("Sam", 70), ("Joe", 52)] = [45,52]
如果列表中的字符串与“ std”字符串不同,则此方法不起作用。我想了解为什么以及如何进行这项工作?谢谢!
答案 0 :(得分:7)
只需更改防护装置| otherwise = listMarks std xs
。我还要在上面的防护措施中进行更改,因为| std == fst x = snd x : listMarks std xs
是的,它们是相等的,但是它使您更清楚地实现了什么。因此您的代码应为:
type StudentMark = (String, Int)
listMarks :: String -> [StudentMark] -> [Int]
listMarks _ [] = []
listMarks std (x:xs)
| std == fst x = snd x : listMarks std xs
| otherwise = listMarks std xs
如您所见,您将使用始终相同的第一个参数来调用该函数,因此很有可能可以编写更整洁的版本。这里有两个简单的想法:
我个人最喜欢的列表理解非常明确和明确:
listMarks' :: String -> [StudentMark] -> [Int]
listMarks' str marks = [m |(n,m) <- marks, n==str]
基本上,您会根据第一个元素过滤列表,然后返回第二个元素。
使用高阶函数map
,filter
和fold
,您可以完成递归和lcs的工作,但看起来却比较整齐。同样,您想基于第一个元素过滤列表,然后返回第二个。
listMarks'' :: String -> [StudentMark] -> [Int]
listMarks'' str = map snd . filter (\(n,_) -> n == str)