簡體   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