Reputation: 9
I want to use a list comprehension to have a string if a certain condition is true but if the condition is not true then put the empty string in (or empty list).
for example : [ Bob | i <- [3..6], i == 4 ]
this gives the list ["Bob"]
but I want to get: [ "" , "Bob" , "" , "" ]
so any empty string whenever i
does not equal 4.
Is it possible to do this within a list comprehension.
Upvotes: 0
Views: 149
Reputation: 714
There is nothing wrong with what you have. It's just you have to force the result whether it meets the condition or doesn't. The way to do that is to put what you have in a list comprehension and have it "execute" a number of times.
[ concat ["Bob" | x == 4] | x <- [3..6] ]
The condition of x not equal 4 produces and empty list '[]' so concat
converts them to identical strings for list uniformity.
Upvotes: -2
Reputation: 477676
The reason this does not work is because you use i == 4
as a filter:
[ "Bob" | i <- [3..6], i == 4 ]
-- ^ filter
So that means that only in case i == 4
, you will add "Bob"
to the list. In case the condition was True
for instance two times (for example i < 5
), then we would yield "Bob"
twice.
The condition is not a filter: it determines what should be added to the list, not on what condition something should be added. In that case you can use function that checks the condition, and returns different results.
We can use bool :: a -> a -> Bool -> a
for this (this is a catamoprhism over Bool
):
import Data.Bool(bool)
[ bool "" "Bob" (i == 4) | i <- [3..6] ]
Note that we can use map
as well:
import Data.Bool(bool)
map (bool "" "Bob" . (4 ==)) [3..6]
Upvotes: 3
Reputation: 54243
Use an if
construction.
[ if i == 4 then "Bob" else "" | i <- [3..6] ]
Though this is probably better without a list comprehension
map f [3..6]
where
f 4 = "Bob"
f _ = ""
Upvotes: 4
Reputation: 747
Left side of the pipe does not have to be a value. You can do it like this: [ if i == 4 then "Bob" else "" | i <- [3..6]]
.
Upvotes: 3