【问题标题】:Haskell- looping every second element of listHaskell-循环列表的每个第二个元素
【发布时间】:2015-02-19 00:35:33
【问题描述】:

我希望能够循环给定列表的每个第二个元素。我可以这样递归地执行此操作:

check validate (x:xs) = check (validate x) (tail xs)

但问题是我需要一个接受列表作为参数的函数,然后返回一个列表,该列表仅由列表中的每个第二个元素组成,从(并包括)列表的第一个元素开始,而我没有认为这是可能的递归。

有人可以告诉我如何使用列表理解吗?这可能是最好的方法。

【问题讨论】:

  • snd . foldr (\x (b, xs) -> (not b, if b then x:xs else xs)) (True, [])

标签: list haskell list-comprehension


【解决方案1】:
second (x:y:xs) = y : second xs;
second _ = []

列表理解可能没有用。

【讨论】:

  • 这看起来不错,但我需要将每个元素保存到一个新列表中,这可能吗?
  • 在 Haskell 中,任何操作都会给你一个新的“对象”。 (除非明确处理“不安全”操作。)因此,到目前为止,此页面上的所有解决方案都为您提供了一个新列表。原因写在这里太长了,请在网上搜索“什么是函数式编程”。
  • 将第一行“=”右边的y改为x。保持“=”左侧不变。
  • @Abhay 你不是还需要一个额外的模式second [x] = x吗?
  • @genisage 是的,谢谢,你是对的,当我们需要第一个元素时。上面的原版没有。更改:second [x] = [x]
【解决方案2】:

你也可以试试相互递归

first [] = []
first (x:xs) = x:second xs

second [] = []
second (x:xs) = first xs

比如

> first [1..10]
[1,3,5,7,9]

> second [1..10]
[2,4,6,8,10]

【讨论】:

    【解决方案3】:

    Haskellish 方法之一是 mapfilterzip

    second xs = map fst $ filter (odd . snd) $ zip xs [1..]
    

    如果您真的想使用列表推导,可以使用并行列表推导扩展。

    {-# LANGUAGE ParallelListComp #-}
    second xs = [ x | (x, n) <- [ (x, n) | x <- xs | n <- [1..] ], odd n ]
    

    不过,我认为前者很简洁。

    【讨论】:

    • 如果你想使用列表推导,而且你对这个压缩和解压缩的东西没问题,为什么不使用[ fst x | x &lt;- (zip xs [1..]), (odd $ snd x) ]
    • 只是为了说明您可以将zip 替换为并行列表解析,也可以将mapfilter 替换为序数列表解析。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2011-06-18
    • 2015-08-18
    • 2015-02-12
    • 1970-01-01
    相关资源
    最近更新 更多