【问题标题】:Remove the 'a' and 'A' characters from two lists and return them as a pair从两个列表中删除 'a' 和 'A' 字符并将它们作为一对返回
【发布时间】:2021-12-09 00:56:21
【问题描述】:

实现 filterA2 :: [Char] -> [Char] -> ([Char], [Char]) 函数,从两个列表中删除字符 'a''A' 并将结果作为一对返回。

例如:

filterA2 "Always" "runAway" == ("lwys", "runwy")

filterA2 "Cherry" "Tree" == ("Cherry", "Tree")

到目前为止,我已经尝试过:

filterA2 [] [] = ([], [])
filterA2 ['a'] ['a'] = ([], [])
filterA2 ['A'] ['A'] = ([], [])
filterA2 ['a'] [xs] = ([], [xs])
filterA2 [xs] ['a'] = ([xs], [])
filterA2 ['A'] [xs] = ([], [xs])
filterA2 [xs] ['A'] = ([xs], [])
filterA2 (x:xs) (y:ys) = filterA2 (xs) (ys)

无论我输入什么,它总是返回("", "")。我可能使用了太多基本案例。

【问题讨论】:

    标签: string haskell char


    【解决方案1】:

    您的方法的问题是:您的模式仅在每个列表中只有一个字符时才有效...

    filterA2 :: [Char] -> [Char] -> ([Char], [Char])
    filterA2 l1 l2 = (remove l1, remove l2)
        where
            remove :: [Char] -> [Char]
            remove [] = []
            remove (x:xs)
                |x == 'A' || x == 'a' = remove xs
                | otherwise = x : remove xs
    

    【讨论】:

    • 有没有其他不包括removewhere的解决方案?
    【解决方案2】:
    import Data.Char (toLower)
    
    filterA2 :: [Char] -> [Char] -> ([Char], [Char])
    filterA2 [] [] = ([], [])
    filterA2 (x:xs) []
      | toLower x == 'a'  = (xs', [])
      | otherwise         = (x:xs', []) where
        (xs', _)          = filterA2 xs []
    filterA2 [] (y:ys)
      | toLower y == 'a'  = ([], ys')
      | otherwise         = ([], y:ys') where
        (_, ys')          = filterA2 [] ys
    filterA2 (x:xs) (y:ys)
      | toLower x == 'a' && toLower y == 'a'  = (xs', ys')
      | toLower x == 'a'                      = (xs', y:ys')
      | toLower y == 'a'                      = (x:xs', ys)
      | otherwise                             = (x:xs', y:ys') where
        (xs', ys') = filterA2 xs ys
    

    如果您需要使用显式递归和模式匹配来实现,上面是使用这些方法的一种方法。当然,使用内置函数会使代码更易于实现和阅读,但您这样做可能是出于教育目的。

    如您所见,有 4 种基本模式,每一种都有特定的情况,根据模式实现为警卫。关键思想是每个函数返回一个由递归函数调用返回的 2 个值组成的元组。

    filterA2 (x:xs) (y:ys) = (x:xs', y:ys') where
      (xs', ys') = filterA2 xs ys
    

    抛开守卫和不同的情况,看看我们是如何创建元组的。所以,撇开 Haskell 的懒惰不谈,即使代码想在每个瞬间尽可能多地计算,它也无法计算函数的返回值,除非它有来自堆栈下方递归调用的返回值。所以,结果是函数沿着递归堆栈向下,直到它到达基本案例模式匹配的底部,因为两个列表都变空了:

    filterA2 [] [] = ([], [])
    

    此时,最低的函数返回它的值,随后它上面的函数也可以计算并返回它的值等等,直到返回最终结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 2021-12-15
      • 2011-09-19
      • 1970-01-01
      相关资源
      最近更新 更多