1
votes

Double boucle for à haskell

J'essaye de faire une nouvelle liste avec le 2ème numéro d'un tuple de si le premier numéro est dans la première liste, ici un exemple helplist [0,2] [(0, "a") , (3, "x"), (5, "y"), (1, "b"), (2, "c")] = ["a", "c"]

J'ai essayé tellement de combinaisons mais sans succès, voici mon code:

helplist :: [Int] -> [(Int,Char)] -> [Char]
helplist (x:xs) ((i,g):gs) | (x == i) = g : helplist xs gs
helplist _ _ = []

En java j'avais fait une boucle 2x for mais dans haskell je connais juste la récursivité. p>


2 commentaires

Ici, vous parcourez les deux listes "simultanément". Mais dans un langage déclaratif, vous ne devriez pas penser en termes de «boucles».


que doit renvoyer helplist [0,2] [(0, "a"), (0, "b")] ?


3 Réponses :


4
votes

Vous pouvez utiliser la compréhension de liste ici:

helplist :: (Foldable f, Eq a) => f a -> [(a, b)] -> [b]
helplist xs gs = concatMap (\x -> map snd (filter (\(i, _) -> x == i) gs)) xs

Ou vous pouvez essayer de filtrer la liste en fonction de la valeur d'une autre liste, comme:

helplist :: Eq a => [a] -> [(a, b)] -> [b]
helplist xs gs = [ g | x <- xs, (i, g) <- gs, x == i ]


2 commentaires

Que fait l'Eq a => ici? ça ne marcherait pas sans ça?


@Kevin: c'est une contrainte de type qui dit que a doit être une instance de la classe de types Eq . Il est nécessaire d'effectuer un x == i . Un Int par exemple est une instance de la classe de types Eq , donc pour [Int] -> [(Int, Char)] -> [Char] , cela fonctionnera. Mais cela fonctionnera donc pour plus de types que de simples Int s ( String s, Char s, Integer s, etc.).



7
votes

Haskell a déjà une fonction pour rechercher une valeur unique dans une liste d'associations:

> import Data.Maybe
> helpList keys table = catMaybes $ map (\x -> lookup x table) keys
> helpList [0,2] [(0,"a"),(3,"x"),(5,"y"),(1,"b"),(2,"c")]
["a","c"]

Tout ce que vous avez à faire est de mapper cela (correctement appliqué à votre list) sur vos clés.

> helpList keys table = map (\x -> lookup x table) keys
> helpList [0,2] [(0,"a"),(3,"x"),(5,"y"),(1,"b"),(2,"c")]
[Just "a",Just "c"]

Eh bien, presque. Cela vous donne une liste de valeurs de Maybe String . Si vous êtes sûr que chaque recherche réussira (ou si vous ne vous souciez tout simplement pas des recherches qui échouent), vous pouvez utiliser la fonction catMaybes de Data.Maybe pour supprimer le Rien et extrayez les valeurs réelles de leurs wrappers Just .

lookup :: Eq a => a -> [(a, b)] -> Maybe b


3 commentaires

Just ["a", "c"] ne serait-il pas un résultat très raisonnable dans ce cas particulier? Donc, sequence pourrait être une fonction pratique ici.


Dans ce cas, il n'y aurait pas de différence claire de signification entre Just [] et Nothing , il semble donc peu de raisons d'avoir un type de retour de Peut-être [a] au lieu de [a] .


Votez pour cette réponse, adorez la réponse qui n'essayez pas de réinventer la roue



3
votes

Il est possible d'écrire Java en Haskell, mais vous n'obtenez aucun avantage de Haskell ou de la programmation fonctionnelle de cette façon. À titre de comparaison avec l'autre réponse, voici Haskell avec un fort accent Java, comme vous l'aviez initialement imaginé:

helplist targets tuples = map snd $ filter (\(x, _) -> x `elem` targets) tuples

Il fait le travail:

*Main> helplist [0,2] [(0,'a'),(3,'x'),(5,'y'),(1,'b'),(2,'c')]
"ac"

Mais comme cette approche ne convient pas à Haskell, elle finit par être à la fois plus longue, plus difficile à écrire et plus difficile à suivre que le code Java équivalent.

Ma suggestion pour le Haskell le plus simple l'implémentation consiste plutôt à dire "Je veux trouver ( filtre ) tous les tuples où le premier élément est dans une liste ( elem ), et pour chacun d'eux ( map ) choisissez le deuxième élément ( snd ):

helplist :: [Int] -> [(Int,Char)] -> [Char]
-- For each thing to find
helplist (x:xs) gs = findOne x gs ++ helplist xs gs
  where
    findOne :: Int -> [(Int,Char)] -> [Char]
    -- For each element in the list
    findOne x ((i,g):gs) | (x == i) = g : findOne x gs
    findOne x (_:gs) = findOne x gs
    findOne _ _ = []
helplist _ _ = []


0 commentaires