为首字母缩写写一个函数,但是我必须写什么条件才能帮助我从“apple apple”中得到“aa”

Eth*_*Lim -1 haskell

我在声明查找我的首字母缩略词的条件时遇到问题。我写的条件是:

  • 如果“head”为空白,则删除空格。
  • 如果 'head' 的下一个字母为空,则删除字母和尾部。
  • 如果“头”和“尾”是字母,我想要“头”。
  • 如果“头”是空白的,请给我下一个字母,因为这是首字母缩略词之一。

但是当遇到像“apple apple”这样的字母时,它会返回“apape”,因为我在处理第三个条件时遇到了问题。

acronym :: String -> String
acronym [] = []
acronym [x] = [x]
acronym (x:y:xs)
  | x == ' '  =  y : acronym xs -- remove if 'head' is blank(space)
  | y == ' '  =  acronym xs     -- remove both x and y if y is blank(space)
  | x `elem` ['a'..'z'] || x `elem` ['A'..'Z'] && y `elem` ['a'..'z'] || y `elem` ['A'..'Z']
              = x : acronym  xs
  | x == ' ' && y `elem` ['a'..'z'] || y `elem` ['A'..'Z'] =  y :acronym xs
  | otherwise = x : y : acronym xs
Run Code Online (Sandbox Code Playgroud)

lef*_*out 5

一些一般性建议:

  1. 避免相等比较,除非您确切地知道为什么需要它们。等式通常最好直接写成模式匹配。
  2. 避免在一个函数中做很多事情。更喜欢组合简单的辅助函数,尤其是当它们已经在库中定义时。
    在你的情况下,这个问题有一个明显的因素
    1. 将字符串拆分为单词
    2. 获取每个单词的第一个字母

即使不是简单地调用该words函数来为您完成大部分工作,编写您自己的函数来从字符串中分离出单个单词也有很大帮助。你可以这样做,例如基于空白和模式匹配,比如

splitOffWord :: String -> (String, String)
splitOffWord "" = ("", "")
splitOffWord (' ':cs) = ("", cs)
splitOffWord (c:cs) = case splitOffWord cs of
   (word, rest) -> (c:word, rest)
Run Code Online (Sandbox Code Playgroud)

...或基于字母度和标准功能

import Data.Char (isAlpha)

splitOffWord = span isAlpha . dropWhile (not . isAlpha)
Run Code Online (Sandbox Code Playgroud)

...或介于两者之间。

然后,在您的acronym函数中,您可以拆分第一个整个单词,使用它来获取首字母缩略词的第一个字符,并递归输入的其余部分。

acronym (' ':str) = acronym str
acronym str = case splitOffWord str of
   (word, rest) -> _ : _
Run Code Online (Sandbox Code Playgroud)

...填写_左边作为练习。