SlippyJoe
SlippyJoe

Reputation: 1

Matching list of lists with other list of lists

Hey guys I have a question about matching lists

Given the list of lists:

Input List 1  = [[True],[False],[True],[[False]]
Input List 2 = [[Bob],[Rick],[Lee],[Bill]]
Input List 3 = [[1],[2],[3],[4]]

Then match the Booleans of list 1 with the other lists so this happens:

Input List 1 + Input List 2 = [[Bob],[Dead],[Lee],[Dead]]
Input List 1 + Input List 2 = [[1],[0],[3],[0]]

Upvotes: 0

Views: 75

Answers (3)

Julia Path
Julia Path

Reputation: 2366

You can use zipWith . zipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]] for matching lists of lists. For example:

import Data.Bool (bool)
kill deadVal = zipWith . zipWith $ bool (const deadVal) id

example = kill 0 [[True, False],[False,True]] [[1,2,3],[2]]
-- example = [[1,0],[0]]

Upvotes: 0

duplode
duplode

Reputation: 34398

As far as I can see, using nested lists here is unnecessary. Without them, all you need is zipWith and an appropriate combining function:

-- The first argument is the "dead" value. Note that this works with any type.
makeDead :: a -> Bool -> a -> a
makeDead dead b val
    | b = val
    | otherwise = dead
GHCi> :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
GHCi> zipWith (makeDead "Dead") [True,False,True,False] ["Bob","Rick","Lee","Bill"] 
["Bob","Dead","Lee","Dead"]

Two variations on the theme. Firstly, if whether a value should be changed depends only on what the value is, then you can simply use map/fmap:

 -- Affects all names with 'i' as the second letter:
lethalLetter :: String -> String
lethalLetter name -> case name of
    (_:'i':_) -> "Dead"
    _ -> name
GHCi> fmap lethalLetter ["Bob", "Rick", "Lee", "Bill"]
["Bob","Dead","Lee","Dead"]

Secondly, you might prefer using Maybe to indicate deadness rather than using an arbitrary value (what if someone is actually called "Dead")?

makeDead' :: Bool -> a -> Maybe a
makeDead' b val
    | b = Just val
    | otherwise = Nothing
GHCi> zipWith makeDead' [True,False,True,False] ["Bob","Rick","Lee","Bill"] 
[Just "Bob",Nothing,Just "Lee",Nothing]

You can then use functions like maybe, fromMaybe and catMaybes (the latter two are in Data.Maybe) to get rid of the Nothings however you feel like doing it:

GHCi> import Data.Maybe
GHCi> foo = zipWith makeDead' [True,False,True,False] ["Bob","Rick","Lee","Bill"]
GHCi> catMaybes foo
["Bob","Lee"]

Upvotes: 2

JonathanZ
JonathanZ

Reputation: 1086

Assuming you change them to lists, as recommended by duplode, how about zipping together the two lists within a list comprehension, something like this:

[if flag then val else defaultVal  | (flag, val) <- zip(list1, list2)]

where defaultVal would have to be specified, but seems to be Dead and 0 for lists 2 and 3.

(I don't have access right now to Haskell, so the syntax may not be 100% there, but that's the idea.)

Upvotes: 0

Related Questions