您的第一个函数会为您提供正确的答案 - 除了它会为您提供语言列表。使用关联列表如何查找与该语言相关的国家/地区?
为此,您只需 swap (Country, Language) 元组中的国家和语言
import Data.Tuple ( swap )
langMap :: [(String, String)] -> [(String, String)]
langMap = map swap
现在,一旦您有了自己的 diff 函数的结果,您只需要将 lookup 函数映射到结果列表上
diff :: [(String, String)] -> [(String, String, String)] -> [String]
diff x y = map (fromJust . (`lookup` langMap')) diffList
where
diffList = Set.toList $ Set.difference (languages x) (translators y)
langMap' = langMap x
如果您担心性能,可以将关联列表替换为Data.Map
import qualified Data.Map as Map
langMap :: [(String, String)] -> Map.Map String String
langMap = Map.fromList . map swap
并且还将diff中的lookup更改为Map.lookup。
diff :: [(String, String)] -> [(String, String, String)] -> [String]
diff x y = map (fromJust . (`Map.lookup` langMap')) diffList
where
diffList = Set.toList $ Set.difference (languages x) (translators y)
langMap' = langMap x
但是,这里有一个警告 - lookup 方法仅适用于每种语言只有一个国家/地区。
如果您想支持有多个国家与同一语言相关联的情况。 langMap-
你需要一些额外的电池
langMap :: [(String, String)] -> Map.Map String [String]
langMap x = Map.fromListWith (++) [(v, [k]) | (k, v) <- x]
这是对this answer 的轻微修改。它创建String 和[String] 的映射。键字符串是语言,值是国家列表
现在,由于 map 的值是一个字符串列表,而不仅仅是一个字符串 - 我们还需要稍微更改一下 diff
diff :: [(String, String)] -> [(String, String)] -> [String]
diff x y = concatMap (fromJust . (`Map.lookup` langMap')) diffList
where
diffList = Set.toList $ Set.difference (languages x) (translators y)
langMap' = langMap x
嗯,这很简单。只需将 map 更改为 concatMap 就足够了 - 它会将字符串列表扁平化为字符串列表。
让我们看看它的实际效果-
λ> xs = [("US", "English"), ("Mexico", "Spanish"), ("France", "French"), ("Spain", "Spanish"), ("UK", "English"), ("Italy", "Italian")]
λ> ys = [("Foo", "Spanish"), ("Bar", "French")]
λ> diff xs ys
["UK","US","Italy"]