Nic*_*kor 2 recursion haskell tuples list
基本上我有这个练习:回忆一下上周的StudentMark类型同义词.写一个递归函数:
listMarks :: String -> [StudentMark] -> [Int]
Run Code Online (Sandbox Code Playgroud)
它给出了特定学生的分数列表; 例如:
listMarks "Joe" [("Joe", 45), ("Sam", 70), ("Joe", 52)] = [45,52]
Run Code Online (Sandbox Code Playgroud)
这就是我编写函数的方式:
type StudentMark = (String, Int)
listMarks :: String -> [StudentMark] -> [Int]
listMarks _ [] = []
listMarks std (x:xs)
| std == fst x = snd x : listMarks (fst x) xs
| otherwise = listMarks (fst x) xs
Run Code Online (Sandbox Code Playgroud)
如果列表中的字符串与"std"字符串不同,则不起作用.我想了解为什么以及如何才能完成这项工作?谢谢!
只需改变警卫| 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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,您使用始终相同的第一个参数调用该函数,因此您很可能编写一个更整洁的版本.这里有两个简单的想法:
就我个人而言,列表理解是非常多才多艺和清晰的:
listMarks' :: String -> [StudentMark] -> [Int]
listMarks' str marks = [m |(n,m) <- marks, n==str]
Run Code Online (Sandbox Code Playgroud)
基本上,您根据第一个元素过滤列表,然后返回第二个元素.
随着高阶函数map,filter并且fold,你可以做尽可能多的递归和LCS,但往往看起来更整洁.您希望再次根据第一个元素过滤列表,然后返回第二个元素.
listMarks'' :: String -> [StudentMark] -> [Int]
listMarks'' str = map snd . filter (\(n,_) -> n == str)
Run Code Online (Sandbox Code Playgroud)