Bob Bobington
Bob Bobington

Reputation: 309

Do some replacement in Haskell List Comprehensions

My questions is if I put in a string containing such as Hello, today is a Nice Day!! How could I get rid of spaces and punctuation and also replacing the uppercase letters with lowercase?

I know how to delete them but not how to replace them.

Also to get rid of the punctuation.

Sorry I don't know how to mess around with strings, only numbers.

testList xs = [if x = [,|.|?|!] then " "  | x<-xs] 

Upvotes: 6

Views: 3180

Answers (6)

Manuel_GG
Manuel_GG

Reputation: 1

Using Applicative Style

A textual quote from book "Learn You a Haskell for Great Good!":

Using the applicative style on lists is often a good replacement for list comprehensions. In the second chapter, we wanted to see all the possible products of [2,5,10] and [8,10,11], so we did this:

[ x*y | x <- [2,5,10], y <- [8,10,11]]         

We're just drawing from two lists and applying a function between every combination of elements. This can be done in the applicative style as well:

(*) <$> [2,5,10] <*> [8,10,11]

This seems clearer to me, because it's easier to see that we're just calling * between two non-deterministic computations. If we wanted all possible products of those two lists that are more than 50, we'd just do:

filter (>50) $ (*) <$> [2,5,10] <*> [8,10,11]
-- [55,80,100,110]

Functors, Applicative Functors and Monoids

Upvotes: 0

Alberto Capitani
Alberto Capitani

Reputation: 1049

import Data.Char

If you want convert the punctuation to space and the characters from upper case to lower case:

testList xs = [if x `elem` ",.?!" then ' ' else toLower x | x<-xs]

Example: testList "TeST,LiST!" == "test list "

If you want to delete the punctuation and convert the characters from upper case to lower case:

testList2 xs = [toLower x | x<-xs, not (x `elem` ",.?!")]

Example: testList2 "Te..S,!t LiS?T" == "test list"

If you don't want or can not import Data.Char, this is an implementation of toLower:

toLower' :: Char -> Char
toLower' char 
    | isNotUppercase = char -- no change required
    | otherwise = toEnum (codeChar + diffLowerUpperChar) -- char lowered
    where
      codeChar = fromEnum char -- each character has a numeric code
      code_A = 65
      code_Z = 90
      code_a = 97
      isNotUppercase = codeChar < code_A || codeChar > code_Z
      diffLowerUpperChar = code_a - code_A

Upvotes: 7

hugomg
hugomg

Reputation: 69934

To get rid of the punctuation you can use a filter like this one

[x | x<-[1..10], x `mod` 2 == 0]

The "if" you are using won't filter. Putting an if in the "map" part of a list comprehension will only seve to choose between two options but you can't filter them out there.

As for converting things to lowercase, its the same trick as you can already pull off in numbers:

[x*2 | x <- [1..10]]

Upvotes: 2

גלעד ברקן
גלעד ברקן

Reputation: 23955

Here's a version without importing modules, using fromEnum and toEnum to choose which characters to allow:

testList xs = 
  filter (\x -> elem (fromEnum x) ([97..122] ++ [32] ++ [48..57])) $ map toLower' xs 
    where toLower' x = if elem (fromEnum x) [65..90] 
                          then toEnum (fromEnum x + 32)::Char 
                          else x

OUTPUT:
*Main> testList "Hello, today is a Nice Day!!"
"hello today is a nice day"

For a module-less replace function, something like this might work:

myReplace toReplace xs = map myReplace' xs where
  myReplace' x
    | elem (fromEnum x) [65..90] = toEnum (fromEnum x + 32)::Char
    | elem x toReplace           = ' '
    | otherwise                  = x

OUTPUT:
*Main> myReplace "!," "Hello, today is a Nice Day!! 123"
"hello  today is a nice day   123"

Upvotes: 0

Chris Barrett
Chris Barrett

Reputation: 3375

You will find the functions you need in Data.Char:

import Data.Char

process str = [toLower c | c <- str , isAlpha c]

Though personally, I think the function compositional approach is clearer:

process = map toLower . filter isAlpha

Upvotes: 4

Oscar Mederos
Oscar Mederos

Reputation: 29823

I've been without writing a code in Haskell for a long time, but the following should remove the invalid characters (replace them by a space) and also convert the characters from Uppercase to Lowercase:

import Data.Char

replace invalid xs = [if elem x invalid then ' ' else toLower x | x <- xs]

Another way of doing the same:

repl invalid [] = []
repl invalid (x:xs) | elem x invalid = ' ' : repl invalid xs
                    | otherwise      = toLower x : repl invalid xs

You can call the replace (or repl) function like this:

replace ",.?!" "Hello, today is a Nice Day!!"

The above code will return:

"hello  today is a nice day  "

Edit: I'm using the toLower function from Data.Char in Haskell, but if you want to write it by yourself, check here on Stack Overflow. That question has been asked before.

Upvotes: 4

Related Questions