[英]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)])]
在解決這個問題之前,您需要對elem
、 map
和foldr
函數有一個很好的理解。 (編輯:也許你不需要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.