Reputation: 1
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
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
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 Nothing
s 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
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