【问题标题】:Using List Comprehension in place of Recursion使用列表理解代替递归
【发布时间】:2013-02-09 23:21:13
【问题描述】:

我很好奇以下示例是否可以使用列表推导代替递归。

函数replaceFirst接受一个元素和一个列表,并替换列表中第一次出现的元素。

这可以使用递归来完成,如下所示:

replaceFirst _ [] = []
replaceFirst elem y (x:xs) | x==y = (elem:xs)
                           | otherwise = x:replaceFirst elem y xs

我的问题是,这个递归函数或类似的对列表中第一次出现的元素进行操作的递归函数可以替换为列表理解函数吗?为什么或者为什么不? (比起实际的代码,我更关心推理)。

【问题讨论】:

标签: haskell


【解决方案1】:

列表理解,灵感来自 leftaroundabout:

replaceFirst elem y xs = [a | let b = break (==y) xs
                                  c = if not (null $ snd b) 
                                         then fst b ++ [elem] ++ tail (snd b) 
                                         else fst b
                              , a <- c]

【讨论】:

    【解决方案2】:

    对于各种形式的map、filter, 和concatMap,列表推导是syntactic sugar。如果您的递归函数可以用这些来描述,那么您可以将其重写为列表推导。它们不能像上面那样短路,也不能通过累积状态。

    你的replaceFirst 似乎需要一个累加器来“告诉”列表中后面的元素关于早期元素的外观。我认为这使得仅使用列表理解语法编写变得困难或不可能。

    【讨论】:

    • +1,感谢您的回复。我很难确定这是否可以单独使用 list comp 来完成,但是您的回答只是澄清并证实了我的第一直觉。谢谢!
    • @MiGusta:是的,当然这并不意味着不能使用 other 标准高阶函数重写该函数。 replaceFirst elem y xs | (l,_:r)&lt;-break(==y)xs = l++[elem]++r | otherwise = xs 会起作用。
    猜你喜欢
    • 1970-01-01
    • 2015-03-10
    • 2020-10-17
    • 2021-01-07
    • 2016-02-06
    • 2011-10-01
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    相关资源
    最近更新 更多