【问题标题】:Haskell delete Chars from StringHaskell 从字符串中删除字符
【发布时间】:2015-08-28 18:55:50
【问题描述】:

我正在尝试编写表单的函数

f :: String -> [String]
f str = ...

返回通过从str 中删除一个字符而形成的所有字符串的列表。例如:

ghci> f "stack"
["tack","sack","stck","stak","stac"]

因为String[Char] 是同义词,我可以使用索引,但我知道你应该避免在Haskell 中这样做。除了使用索引还有什么更好的方法吗?

【问题讨论】:

    标签: string haskell char


    【解决方案1】:

    你可以像这样使用递归:

    f :: [a] -> [[a]]
    f [] = []
    f (s:ss) = ss : map (s:) (f ss)
    

    【讨论】:

    • Right;对于那个很抱歉。但是,使基本情况和一般情况返回相同类型的值不是一种好习惯吗?你的答案可以相应修改吗?
    • 我不确定你的意思。它们属于同一类型;否则它不会编译。一般[] :: [b],在这种情况下b ~ [a]
    • Jubobs:是的,空列表与包含空列表的列表不同。但它们都是同一类型(否则您无法比较它们是否相等)。
    • @rampion 好的。我现在明白了。我刚刚学到了一些东西:)
    • 考虑如果f [] = [[]] 会发生什么。然后f "a" = f ('a':[]) = [] : map ('a':) (f []) = [] : map ('a':) ([[]]) = [] : ['a':[]] = [] : ["a"] = [ [], "a" ]
    【解决方案2】:

    Josh Kirklin 的单线解决方案:

    f = tail . foldr (\x ~(r:rs) -> (x : r) : r : map (x :) rs) [[]]
    

    【讨论】:

    • @Johannes Kuhn,没有。这个版本更具可读性:f = snd . foldr (\x ~(r, rs) -> (x : r, r : map (x :) rs)) ([], [])
    【解决方案3】:

    也许更易读的描述方式是:

    gaps :: [a] -> [[a]]
    gaps xs = zipWith removeAt [0..] $ replicate (length xs) xs
    
    removeAt i xs = ys ++ zs
        where
            (ys,_:zs) = splitAt i xs
    

    但实际上,它比其他解决方案要慢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-12
      • 2018-08-10
      • 2016-07-26
      • 2013-09-18
      相关资源
      最近更新 更多