哈斯克尔.两个列表的INNER JOIN



我一直在询问谷歌,并试图找到必要的工具来完成这项工作,但似乎找不到解决问题的方法。整个任务是使用字典来翻译列表,并只保留唯一的值。例如以下输入:

dict = [("a", "aa"), ("b", "bb")]
list1 = ["a","b","c","a","a","g"]

应该产生以下输出:

result = ['aa', 'bb']

这就是我目前所处的位置:

main = do
let dict = [("a", "aa"), ("b", "bb")]
let list1 = ["a","b","c","g"]
let keys = map fst dict
let values = map snd dict
let result = replace keys values list1
print(result)

产生

["aa","bb","c","g"]

因此,为了解决这个问题,我想可能有一种方法可以使用filtermapfoldl进行内部连接,如下所示:

let result = innerJoin values result

目前我有这样的东西:

innerJoin :: (Eq a) =>[a] -> [a] -> [a]
innerJoin xs     []     = xs
innerJoin []     ys     = ys
innerJoin (x:xs) (y:ys) = if (elem x (y:ys))
then x: innerJoin xs ys
else innerJoin xs ys

main = do
let dict = [("a", "aa"), ("b", "bb")]
let list1 = ["a","b","c","g"]
let keys = map fst dict
let values = map snd dict
let list2 = innerJoin keys list1
let result = replace keys values list2
print(result)

但是它返回["aa","bb","c","g"]而不是预期的["aa","bb"]。最后,我计划用nub来完成它,但我正在努力弄清楚innerJoin部分。

编辑:

感谢下面的答案,这里是问题的解决方案:

innerJoin xs     []     = []
innerJoin []     ys     = []
innerJoin (x:xs) (y:ys) = if (elem x (y:ys))
then x: innerJoin xs ys
else innerJoin xs ys
catMaybes ls = [x | Just x <- ls]
genList x [] = []
genList [] y = []
genList x (y:ys) = lookup y x: genList x ys
func dict list =  do
let keys = map fst dict
let list1 = innerJoin keys list
catMaybes (genList dict list1)
test1 = func [("a", "aa"),("e", "bb")] ["a","b","c","g","a"]
test2 = func [(1,11),(2,11),(4,44)] [1,2,3,1,2]

您想要的函数是lookup。例如:

lookup "a" [("a", "aa"), ("b", "bb")] = Just "aa"
lookup "b" [("a", "aa"), ("b", "bb")] = Just "bb"
lookup "x" [("a", "aa"), ("b", "bb")] = Nothing   -- "x" is not in the list

这里有用的另一个函数是Data.Maybe.catMaybes:如果你有一个像[Just 1, Just 2, Nothing, Just 3, Nothing]这样的列表,并将catMaybes应用于它,你就会得到[1, 2, 3]。因此,您可以将lookupcatMaybes组合起来,得到catMaybes $ map (flip lookup dict) list1作为您想要的解决方案。另一个改进是注意Data.MaybemapMaybe f xs定义为等效于catMaybe (map f xs),因此可以将其简化为mapMaybe (flip lookup dict) list1

最新更新