[英]Haskell List Duplicates (if possible with map, elem and foldr)
My Task is to take in Data and "filter" out every duplicate like in the example down below.我的任务是接收数据并“过滤”出每个重复项,如下面的示例所示。 If possible, I have to use the functions map, elem and foldr I honestly don't know how to do it, if anyone can give me a hint on how to solve the problem, I'd be grateful.
如果可能,我必须使用函数 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)])]
Before you can solve this problem, you need to have a good understanding of the functions elem
, map
and foldr
.在解决这个问题之前,您需要对
elem
、 map
和foldr
函数有一个很好的理解。 (Edit: maybe you won't need filter
. I originally read foldr
as filter
, but there are some useful details in that section that will help so I left it. (编辑:也许你不需要
filter
。我最初将foldr
读为filter
,但该部分中有一些有用的细节会有所帮助,所以我离开了。
If you have some prior programming experience, elem
should not be hard.如果你之前有一些编程经验,
elem
应该不难。 When learning new functions in Haskell, we usually start with the type signature because it can give us a lot of information.在 Haskell 中学习新函数时,我们通常从类型签名开始,因为它可以给我们很多信息。 For
elem
it is a -> [a] -> Bool
.对于
elem
它是a -> [a] -> Bool
。 This means it takes two parameters, a value of type a
and a list of values of type a
, then it returns a Bool
.这意味着它有两个参数,类型的值
a
和类型的值的列表a
,那么它返回一个Bool
。 If the value is in the list than it returns True
otherwise it returns False
.如果该值在列表中,则返回
True
否则返回False
。
> elem 1 [1,2,3]
True
> elem "car" ["boat","bus","airplane"]
False
In a lot of Haskell code you will probably see elem
used in infix style by wrapping it in backticks.在许多 Haskell 代码中,您可能会看到
elem
通过将其包装在反引号中而以中缀样式使用。
> 1 `elem` [1,2,3]
True
> "car" `elem` ["boat","bus","airplane"]
False
Again we will start with the type signature.我们再次从类型签名开始。 For
filter
it is (a -> Bool) -> [a] -> [a]
.对于
filter
它是(a -> Bool) -> [a] -> [a]
。 filter
takes two parameters, (a -> Bool)
is a function f
that takes one parameter of type a
and returns a Bool
, and [a]
is a list of values of type a
. filter
采用两个参数, (a -> Bool)
是一个函数f
即采用类型的一个参数a
,并返回一个Bool
,并且[a]
是类型的值的列表a
。 It will evaluate function f
on each value on the list.它将对列表中的每个值计算函数
f
。 When f
returns False
it will ignore that item, when f
returns True
, it will collect it and add it to a new list that it returns.当
f
返回False
,它将忽略该项目,当f
返回True
,它将收集它并将其添加到它返回的新列表中。 Here some examples.这里有一些例子。
> even [1,2,3,4,5,6]
[2,4,6]
> odd [1,2,3,4,5,6]
[1,3,5]
Before we go any further it will be helpful to understand what lambda functions are (also called anonymous functions).在我们继续之前,了解什么是 lambda 函数(也称为匿名函数)会很有帮助。 They are a way to define a function without giving a name to the function.
它们是一种定义函数而不给函数命名的方法。 It also let's us define a function in line.
它还让我们在线定义一个函数。 The syntax looks like this
(\\x -> ...)
where x
is the name of the parameter we pass in and ...
should be replaced with a function body.语法看起来像这样
(\\x -> ...)
其中x
是我们传入的参数的名称,并且...
应该替换为函数体。 Now let's try to define some lambda functions for filter
(remember that they have to return Bool
).现在让我们尝试为
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"]
Finally map
has a type signature that looks like this (a -> b) -> [a] -> [b]
.最后
map
有一个类型签名,看起来像这样(a -> b) -> [a] -> [b]
。 (a -> b)
is a function f
that takes a value of type a
and returns a value of type b
, [a]
is a list of values of types a
, then it returns [b]
which is a list of values of type [b]
. (a -> b)
是一个函数f
,它接受一个类型a
a 的值并返回一个类型为b
的值, [a]
是一个类型a
的值列表,然后它返回[b]
这是一个值的列表输入[b]
。 It evaluates the function f
on each value in the list and returns a list with the same number of elements, but the values might be altered.它对列表中的每个值计算函数
f
并返回一个具有相同元素数量的列表,但这些值可能会改变。 Here are a few examples.这里有一些例子。
-- 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
is a bit more complicated. foldr
有点复杂。 Its type signature for a list is (a -> b -> b) -> b -> [a] -> b
.它的列表类型签名是
(a -> b -> b) -> b -> [a] -> b
。 After you are comfortable with map
, I would take a look at thisStack Overlow question on foldr .在您对
map
感到满意后,我会看一下有关 foldr 的 Stack Overlow 问题。
You may also need to understand also understand pattern matching on tuples.您可能还需要了解元组上的模式匹配。 Haskell Pattern Matching .
Haskell 模式匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.