我正在编写以下类型的函数:
match :: [(String,a)] -> Maybe (String, a, a)
我希望函数遍历元组列表,并确定是否存在第一个元素(字符串)相同的元组。如果是这样,我想返回一个包含该字符串的元组,以及每个匹配元组中的第二个元素。如果没有匹配的元组,则返回“Nothing”。如果有多个匹配,则返回它找到的第一个匹配。
例如:
match [("x", 3), ("y", 4), ("z", "5"), ("x", 6)] = ("x", 3, 6)
match [("x", 3), ("y", 4), ("z", "5")] = Nothing
我在想:
match (x:xs) = if (fst x) = (fst xs) return (fst x, snd x, snd xs)
--if no matches, return Nothing
感谢您的帮助!
答案 0 :(得分:2)
如果有三个或四个带有“x”的元组怎么办?你不能拥有可变长度的元组。也许你想要返回一个列表:
match :: [(String, a)] -> Maybe (String, [a])
如果有几个元组相匹配怎么办?你想要所有这些,还是仅仅是第一个?如果你想要它们,那么你应该返回一个匹配列表。
match :: [(String, a)] -> [(String, [a])]
如果您这样想,那么您可以看到将所有“x”对分组在一起,“y”对等等,将是一个良好的开端。您可以使用
执行此操作sortBy (comparing fst) xs
comparing
接受一个函数和两个值,将函数应用于每个函数,并比较结果。 sortBy
使用其第一个参数作为比较函数,因此sortBy (comparing fst)
按照每个元组中的第一个元素对列表进行排序。
然后您可以使用groupBy
一起收集元素。
编辑:
groupBy
的类型为
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
因此,您需要编写函数equalFirst
以将其作为参数提供。那么
groupBy equalFirst $ sortBy (comparing fst) xs
会给你
[[("x", 3), ("x", 6)], [("y", 4)], [("z", 5)]]
这是一个列表清单。每个子列表都包含具有相同字母的元组。
现在你可以编写一个函数,它接受其中一个子列表并将其转换为你想要的结果。然后使用map
将其应用于列表列表。