Kaylo
Kaylo

Reputation: 326

Haskell : Filtering a list of strings

I have a list of Strings I want to filter through. My predicate is that the string should begin with an uppercase letter.

eg. when I run onlyLowercase ["boy", "girl", "Hi"]

it should give me a list of ["boy", "girl"]

I can do it using pattern matching and guards, but I'm using the learnyouahaskell (http://learnyouahaskell.com) book and I came across the topic on higher-order functions. I read about the filter function and thought it could achieve what I want to do in far fewer lines of code.

Using pattern Matching/Guards (This works well and solves my problem)

onlyLowercase :: [[Char]] -> [[Char]]
onlyLowercase [] = []
onlyLowercase (x:xs) 
  | isLower (head x) = x : onlyLowercase xs  
  | otherwise = onlyLowercase xs

Using the filter function

onlyLowercase2 :: [String] -> [String]
onlyLowercase2 [] = []
onlyLowercase2 (x:xs) = filter isLower x : onlyLowercase2 xs

Unfortunately, when I run onlyLowercase2 ["boy", "girl", "Hi"], I get a list of ["boy", "girl", "i"].

I want to know if there's a way I can filter my list of strings using the first character in my string (without creating any auxiliary function that could check the String and return true if the first letter is lowercase).

I also tried using

 onlyLowercase2 (x:xs) = filter (isLower head x) : onlyLowercase2 xs

but that didn't even compile. Basically, I'm just trying to figure out how the filter function can be used on a list of lists. Thank you, in advance, for any assistance rendered.

Upvotes: 2

Views: 2642

Answers (2)

dopamane
dopamane

Reputation: 1315

Using Data.List and Data.Char:

import Data.List
import Data.Char

onlyLowerCase :: [String] -> [String]
onlyLowerCase = filter (all isLower)

I use the all function which checks that all elements of a list satisfy a predicate. In this case all isLower will return true if all letters in a String are lowercase. Then just filter the Strings that are all lowercase. The Haskell Report has a good reference for List and Char functions among other useful libraries.

Upvotes: 1

Kaylo
Kaylo

Reputation: 326

Thanks to Willem Van Onsem's suggestion to use a lambda expression as a filter function, I read further and came up with this 2 line solution.

onlyLowercase2 :: [String] -> [String]
onlyLowercase2 = filter (\st-> ("" /= st) && (isLower $ head st))

Not sure if it's perfect, but at least it's working.

Upvotes: 5

Related Questions