2016-11-12 60 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:然後使用模式匹配將結果列表轉換爲所需的三元組元組。 –