简体   繁体   English

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

[英]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 .在解决这个问题之前,您需要对elemmapfoldr函数有一个很好的理解。 (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 ,但该部分中有一些有用的细节会有所帮助,所以我离开了。

elem元素

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

filter筛选

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"]

map地图

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文件夹

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 问题

pattern matching模式匹配

You may also need to understand also understand pattern matching on tuples.您可能还需要了解元组上的模式匹配。 Haskell Pattern Matching . Haskell 模式匹配

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

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