2016-11-12 80 views
-3

我写了以下类型的函数:元组评价

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

我认为(“z”,“5”)是一种印刷错误,因为没有其他数字有引号。 –

回答

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将其应用于列表。

+0

对于这个函数,我们假设只有一个匹配的元组,并且只有两个元组具有“x” –

+0

@ Sarah.S:然后使用模式匹配将结果列表转换为所需的三元组元组。 –