繁体   English   中英

Haskell 列表重复项(如果可能,使用 map、elem 和 foldr)

[英]Haskell List Duplicates (if possible with map, elem and foldr)

我的任务是接收数据并“过滤”出每个重复项,如下面的示例所示。 如果可能,我必须使用函数 map、elem 和 foldr 我真的不知道该怎么做,如果有人能给我一个如何解决问题的提示,我将不胜感激。

type StudentName = String
type CourseName  = String
type ExamScore   = (CourseName, Float)
type StudentData = [(StudentName, [ExamScore])]

students :: StudentData
students = [
 ("Tim Berners-Lee", [("Maths", 1.3), ("Algorithm", 2.0)]), 
 ("Ada Lovelace",[("Info 1", 3.0), ("Lambda-Maths", 1.7), ("Science", 2.3), ("Data Mining", 2.7)]),
 ("Alan Turing", [("Maths", 1.7), ("operatingSystems", 2.0), ("Lambda-Maths", 1.7)]),
 ("Alonzo Church", [("Info 2", 2.7), ("Systems", 2.3), ("Lambda-Maths", 1.0), ("Algorithm", 3.0)]),
 ("Bjarne Stroustrup", [("Info 1", 2.7), ("Info 2", 1.3), ("operatingSystems", 2.0), ("Topology", 2.3)]),("Bjarne Stroustrup", [("Info 1", 2.7), ("Info 2", 1.3), ("operatingSystems", 2.0), ("Topology", 2.3)]),
 ("Donald E. Knuth", [("Maths", 3.3), ("Info 2", 1.7), ("Lambda-Maths", 2.0), ("Science", 4.0)]),
 ("Grace Hopper", [("Info 3", 1.0), ("operatingSystems", 2.3), ("Systems", 1.7)]),
 ("Annie Easley", [("Maths", 1.0), ("Info 2", 1.7)]),
 ("Edsger W. Dijkstra", [("Topology", 3.3), ("Algorithm", 2.7), ("Systems", 4.0)]),
 ("John von Neumann", [("Maths", 3.3), ("Algoritmische Topologie", 1.0), ("operatingSystems", 1.3), ("Systems", 5.3)])
 ]

courses :: [CourseName]
courses = ["Maths", "Info 1", "Info 2", "Algorithm", "operatingSystems", "Topology", "Lambda-Maths", "Systems", "Science", "Data Mining"]

examResults :: [ExamScore]
examResults = [("Maths", 3.3), ("Topology", 1.0), ("operatingSystems", 1.3), ("Systems", 5.3), ("Info 1", 1.7), ("Info 2", 1.7), ("Data Mining", 0.3)]





filterDuplicates :: StudentData -> StudentData
filterDuplicates



--e.g.
-- filterDuplicates [("Tom", [("Course A", 1.3), ("Course B", 2.0)]), ("Tom", [("Course A", 1.3), ("Course B", 2.0)])]
-- output: [("Tom", [("Course A", 1.3), ("Course B", 2.0)])]

在解决这个问题之前,您需要对elemmapfoldr函数有一个很好的理解。 (编辑:也许你不需要filter 。我最初将foldr读为filter ,但该部分中有一些有用的细节会有所帮助,所以我离开了。

元素

如果你之前有一些编程经验, elem应该不难。 在 Haskell 中学习新函数时,我们通常从类型签名开始,因为它可以给我们很多信息。 对于elem它是a -> [a] -> Bool 这意味着它有两个参数,类型的值a和类型的值的列表a ,那么它返回一个Bool 如果该值在列表中,则返回True否则返回False

> elem 1 [1,2,3]
True
> elem "car" ["boat","bus","airplane"]
False

在许多 Haskell 代码中,您可能会看到elem通过将其包装在反引号中而以中缀样式使用。

> 1 `elem` [1,2,3]
True
> "car" `elem` ["boat","bus","airplane"]
False

筛选

我们再次从类型签名开始。 对于filter它是(a -> Bool) -> [a] -> [a] filter采用两个参数, (a -> Bool)是一个函数f即采用类型的一个参数a ,并返回一个Bool ,并且[a]是类型的值的列表a 它将对列表中的每个值计算函数f f返回False ,它将忽略该项目,当f返回True ,它将收集它并将其添加到它返回的新列表中。 这里有一些例子。

> even [1,2,3,4,5,6]
[2,4,6]
> odd [1,2,3,4,5,6]
[1,3,5]

在我们继续之前,了解什么是 lambda 函数(也称为匿名函数)会很有帮助。 它们是一种定义函数而不给函数命名的方法。 它还让我们在线定义一个函数。 语法看起来像这样(\\x -> ...)其中x是我们传入的参数的名称,并且...应该替换为函数体。 现在让我们尝试为filter定义一些 lambda 函数(记住它们必须返回Bool )。

-- keep numbers greater than zero
> filter (\x -> x > 0) [-1,-2,3,5,0,-4,100] 
[3,5,100]
-- keep lists (Strings) longer than 3
> filter (\x -> length x > 3) ["the", "a", "hello", "goodnight", "bye"]
["hello", "goodnight"]

地图

最后map有一个类型签名,看起来像这样(a -> b) -> [a] -> [b] (a -> b)是一个函数f ,它接受一个类型a a 的值并返回一个类型为b的值, [a]是一个类型a的值列表,然后它返回[b]这是一个值的列表输入[b] 它对列表中的每个值计算函数f并返回一个具有相同元素数量的列表,但这些值可能会改变。 这里有一些例子。

-- here type a is Int and type b is also Int
-- add one to every element in the list
> map (\x -> x + 1) [1,2,3,4]
[2,3,4,5]

-- here type a is String and type b is also String
-- append a "." to every String in the list
> map (\x -> x ++ ".") ["hello", "goodbye"]
["hello.", "goodbye."]

-- here type a is String and type b is Int
> map (\x -> length x) ["hello", "goodbye"]

-- here type a is Int and type b is String
> map (\x -> show x) [1,2,3,4]
["1","2","3","4"]

文件夹

foldr有点复杂。 它的列表类型签名是(a -> b -> b) -> b -> [a] -> b 在您对map感到满意后,我会看一下有关 foldr 的 Stack Overlow 问题

模式匹配

您可能还需要了解元组上的模式匹配。 Haskell 模式匹配

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM