Haskell. INNER JOIN z dwóch list

Nov 08 2020

Pytałem Google i próbuję znaleźć potrzebne narzędzia, ale nie mogę znaleźć rozwiązania mojego problemu. Całe zadanie polega na użyciu słownika do przetłumaczenia listy i zachowania tylko unikalnych wartości. Na przykład następujące dane wejściowe:

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

mają dać następujący wynik:

result = ['aa', 'bb']

Tutaj utknąłem do tej pory:

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)

która daje

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

Tak aby rozwiązać ten Myślałam, że może być sposobem użycia filterlub mapczy foldlw jakiś sposób zrobić sprzężenie wewnętrzne, co następuje:

let result = innerJoin values result

Obecnie mam coś, co wygląda tak:

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)

Ale wraca ["aa","bb","c","g"]i nie jest oczekiwany ["aa","bb"]. W końcu planuję to zakończyć nub, ale walczę z odgadnięciem części innerJoin.

EDYTOWAĆ:

Dzięki poniższej odpowiedzi tutaj jest rozwiązanie problemu:

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]

Odpowiedzi

3 bradrn Nov 08 2020 at 10:21

Funkcja, której potrzebujesz, to lookup. Na przykład:

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

Inna funkcja, która jest tutaj przydatna to Data.Maybe.catMaybes: jeśli masz listę polubień [Just 1, Just 2, Nothing, Just 3, Nothing]i zastosujesz się catMaybesdo niej, otrzymasz [1, 2, 3]. Możesz więc po prostu połączyć lookupi catMaybesuzyskać catMaybes $ map (flip lookup dict) list1pożądane rozwiązanie. Dodatkowym udoskonaleniem jest zauważenie, że Data.Maybedefiniuje się mapMaybe f xsjako równoważne catMaybe (map f xs), więc można to uprościć do mapMaybe (flip lookup dict) list1.