Kevin
Kevin

Reputation: 145

Double for loop in haskell

I'm trying to make a new list with the 2nd number of a tuple of if the first number is in the first list, here a example helplist [0,2] [(0,"a"),(3,"x"),(5,"y"),(1,"b"),(2,"c")] = ["a","c"]

I've tryed so many combinations but without success, here my code:

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

In java I'd done a 2x for loop but in haskell I just know recursion.

Upvotes: 1

Views: 392

Answers (3)

that other guy
that other guy

Reputation: 123420

It's possible to write Java in Haskell, but you don't get any benefits from Haskell or functional programming that way. For comparison with the other answer, here's Haskell with a strong Java accent, the way you initially imagined:

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 _ _ = []

It does the job:

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

But since this approach is a bad fit for Haskell, it ends up being both longer, more awkward to write, and harder to follow than the equivalent Java code.

My suggestion for the most straight forward Haskell implementation is instead to say "I want to find (filter) all tuples where the first element is in a list (elem), and for each of them (map) pick the second element (snd):

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

Upvotes: 3

chepner
chepner

Reputation: 530970

Haskell already has a function for looking up a single value in an association list:

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

All you need to do is map that (appropriately applied to your list) over your keys.

> 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"]

Well, almost. This gives you back a list of Maybe String values. If you are sure each lookup will succeed (or simply don't care about lookups that fail), you can use the catMaybes function from Data.Maybe to drop the Nothing responses and extract the actual values from their Just wrappers.

> 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"]

Upvotes: 7

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476554

You can use list comprehension here:

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

Or you can try to filter the list based on the value of another list, like:

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

Upvotes: 4

Related Questions