Set a是类型为a的唯一值序列。这些值必须属于comparable类型(Int、Float、Time、Char、String,以及由可比较类型组成的元组或数组)。
你可以用Set.toList和Set.fromList在数组和集合之间互相转换。由于Set的内部结构,从Set.fromList得到的数组保证是有序的。
Set.fromList [2, 3, 3, 3, 1, 1, 2]
--> Set.fromList [1, 2, 3]
Set.toList (Set.fromList [2, 3, 3, 3, 1, 1, 2])
--> [1, 2, 3]
你可以用Set.empty、Set.singleton、Set.insert和Set.remove来创建和填充集合。
Set.empty
--> Set.fromList []
Set.singleton "hi"
--> Set.fromList ["hi"]
eightyEight = Set.singleton 88
Set.insert 88 eightyEight
--> Set.fromList [88]
Set.insert 89 eightyEight
--> Set.fromList [88, 89]
Set.remove 88 eightyEight
--> Set.fromList []
Set.remove 89 eightyEight
--> Set.fromList [88]
你可以用Set.member、Set.isEmpty和Set.size这几个函数查询集合的内容。
Set.member 88 eightyEight
--> True
Set.isEmpty eightyEight
--> False
Set.size eightyEight
--> 1
集合还可以用Set.union、Set.intersect和Set.diff组合起来。
a = Set.fromList [1, 10, 100]
b = Set.fromList [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Set.union a b
--> Set.fromList [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
Set.intersect a b
--> Set.fromList [1, 10]
Set.diff a b
--> Set.fromList [100]
Set.diff b a
--> Set.fromList [2, 3, 4, 5, 6, 7, 8, 9]
你可以对集合进行过滤和划分。
even n = modBy 2 n == 0
Set.filter even b
--> Set.fromList [2, 4, 6, 8, 10]
Set.partition even b
--> (Set.fromList [2, 4, 6, 8, 10], Set.fromList [1, 3, 5, 7, 9])
你对 Blorkemon™️ 卡牌的怀旧之情丝毫没有减退,你甚至又开始收集它们,还拉着朋友们一起加入。
在本练习中,Card收藏由Set Card表示,因为当你的目标是集齐所有现有卡牌时,重复的卡牌并不重要。
你非常希望朋友们加入你的 Blorkemon™️ 狂热,最好的办法就是送他们一张卡牌,帮他们开启收藏。
实现newCollection,它把一张卡牌转换成一个收藏。
newCollection "Newthree"
--> Set.fromList ["Newthree"]
一旦你有了收藏,它就会有自己的生命,必须不断壮大。
实现addCard,它接收一个Card和一个收藏,并返回一个Tuple,其中包含两个值:一个Bool,表示该Card是否已经在收藏中;以及添加了该卡牌后的收藏。
addCard "Scientuna" (Set.fromList ["Newthree"])
--> (False, Set.fromList ["Newthree", "Scientuna"])
既然你的朋友们又为 Blorkemon™️ 疯狂了,你就可以借此通过交换卡牌来扩充自己的收藏。
并不是每一笔交易都值得做,或者根本没法做。
你不能交换一张自己没有的卡牌,也不应该用一张卡牌去换一张你已经有的卡牌。
实现tradeCard,它接收两张要交换的卡牌(你的和对方的)以及你当前的收藏。
返回值是一个包含两个值的Tuple:一个Bool,说明这笔交易是否可行且值得做;以及如果你做了这笔交易最终会得到的收藏(即使实际上并不可行)。
tradeCard "Scientuna" "Newthree" (Set.fromList ["Scientuna"])
--> (True, Set.fromList ["Newthree"])
你在跳蚤市场发现了一批旧卡牌。
你必须对卡牌排序并去除重复项,以便把这个列表和你的收藏进行比较。
实现removeDuplicates,它会对一个卡牌列表排序,并返回一个排序后、去重后的卡牌列表。
removeDuplicates ["Newthree", "Newthree", "Newthree", "Scientuna"]
--> ["Newthree", "Scientuna"]
是时候为你的收藏感到高兴了。
实现extraCards,它接收你的收藏和另一个收藏,并返回另一个收藏没有的卡牌数量。
extraCards (Set.fromList ["Scientuna"]) (Set.fromList ["Newthree", "Scientuna"])
--> 0
你和热衷 Blorkemon™️ 的朋友们聚在一起,想知道哪些卡牌最常见。
实现boringCards,它接收一个收藏列表,并返回一个排序后的卡牌列表,这些卡牌是所有收藏都有的。
boringCards [Set.fromList ["Scientuna"], Set.fromList ["Newthree", "Scientuna"]]
--> ["Scientuna"]
你和朋友们加起来是否拥有所有的 Blorkemon™️ 卡牌?
实现totalCards,它接收一个收藏列表,并返回所有收藏中不同卡牌的总数。
totalCards [Set.fromList ["Scientuna"], Set.fromList ["Newthree", "Scientuna"]]
--> 2
你的侄子很快要来看你,你想给他留下深刻印象。
小孩子都喜欢闪亮的东西,对吧?
Blorkemon™️ 卡牌也可以是闪亮的!
实现splitShinyCards,它接收一个收藏,并返回一个Tuple,其中包含两个排序后的卡牌列表:一个列表包含所有以"Shiny"开头的卡牌,另一个列表包含其余卡牌。
splitShinyCards (Set.fromList ["Newthree", "Scientuna", "Shiny Scientuna"])
--> (["Shiny Scientuna"], ["Newthree", "Scientuna"])