Haskell - 根据某些条件过滤字符串列表

Joh*_*ohn 2 string haskell list filter

我是这个社区的新人.我学习Haskell并且遇到Haskell编码问题.我希望你能帮助我.

我在这里和谷歌搜索,没有任何成功.

我的问题是fowllows:我想编写一个函数,它将列表作为参数,如下所示:

myStringListFilter :: [String] -> [String]
Run Code Online (Sandbox Code Playgroud)

处理以下步骤:

  1. 删除第一个字母

    myStringListFilter myList = map tail strListe myList
    
    Run Code Online (Sandbox Code Playgroud)
  2. 过滤列表中以"u"或"U"开头的每个元素.

    myStringListFilter myList = filter (´elem´ ['u', 'U']) (map tail strListe myList)
    
    Run Code Online (Sandbox Code Playgroud)

第二步不起作用.我收到错误.

如果我需要以下内容,如何实现解决方案:

Input: ["butter", "chees", "aUbergine", "egg", "milk", "bUbble", "curry"]

Output: ["chees", "egg", "milk"]
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 8

类型filter

filter :: (a -> Bool) -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)

所以如果你想String根据谓词过滤一个s 的列表,你需要一个函数String -> Bool,但你写的(`elem` ['u',U'])是类型Char -> Bool.

所以你需要一个功能

beginsWithU :: String -> Bool
Run Code Online (Sandbox Code Playgroud)

最简单的定义方法是

beginsWithU (c:_) = c == 'u' || c == 'U'
beginsWithU _ = False                      -- empty list
Run Code Online (Sandbox Code Playgroud)

然后你误解了filter它是如何工作的,它保持元素满足谓词,你想要删除它们,所以你需要用一个not(或doesn'tbeginWithU直接定义)组成谓词.

但是,正如7stud 指出的那样,您实际上并不想要从原始列表中更改要保留的元素

myStringListFilter myList = filter (not . beginsWithU) (map tail myList)
Run Code Online (Sandbox Code Playgroud)

或者,无点:

myStringListFilter = filter (not . beginsWithU) . map tail
Run Code Online (Sandbox Code Playgroud)

会实现的.所以你需要将它合并tail到谓词中,并且不需要map,这会产生

myStringListFilter = filter (not . beginsWithU . tail)
Run Code Online (Sandbox Code Playgroud)

或者,如果String输入清单中出现空白的可能性应予以良好处理,

myStringListFilter = filter (not . beginsWith . drop 1)
Run Code Online (Sandbox Code Playgroud)

因为tail ""将产生*** Exception: Prelude.tail: empty listdrop 1 ""产生"".

但是,由于您希望保留原始列表元素,您还可以定义谓词以直接查看第二个字符,

secondCharIsU :: String -> Bool
secondCharIsU (_:c:_) = c == 'u' || c == 'U'
secondCharIsU _       = False

myStringListFilter = filter (not . secondCharIsU)
Run Code Online (Sandbox Code Playgroud)

  • @zurgl然后我不会称之为`startsWithU`,我在问题中使用`map tail`导致误入歧途,并且没有仔细查看所需的输出. (2认同)

7st*_*tud 5

建议的解决方案:

beginsWithU (c:_) = c == 'u' || c == 'U'
beginsWithU _ = False      

myStringListFilter myList = filter (not . beginsWithU) (map tail myList)


ghci>myStringListFilter ["butter", "cheese", "aUbergine", "egg", "milk", "bUbble", "curry"] 
["heese","gg","ilk"]
Run Code Online (Sandbox Code Playgroud)

...不会产生正确的输出。

映射会更改原始字符串,因此过滤映射字符串的列表将不会生成包含任何原始字符串的列表。该操作需要使用自定义过滤器来过滤原始列表:

myFilter :: String -> String -> Bool
myFilter notAllowedChars str = 
    if head (tail str)  `elem` notAllowedChars
    then False    --if match, reject this string
    else True     --if no match, include this string in result list 


ghci>filter (myFilter "uU") ["butter", "cheese", "aUbergine", "egg", "milk", "bUbble", "curry"] 
["cheese","egg","milk"]
Run Code Online (Sandbox Code Playgroud)

无点:

filterBy :: String -> String -> Bool
filterBy notAllowedChars = 
    not . (`elem` notAllowedChars) . head . tail 
Run Code Online (Sandbox Code Playgroud)

请记住,字符数组(例如 ['u', 'U'])与字符串“uU”相同。