【问题标题】:Haskell function that goes through each pair in list and returns a list with size smaller than original by 1Haskell 函数遍历列表中的每一对并返回一个大小比原始列表小 1 的列表
【发布时间】:2018-12-24 22:04:01
【问题描述】:

假设我们有列表 [1,2,3,4]。 我想获取每对连续元素(即(1,2),(2,3),(3,4)),将它们应用于某个函数,并返回包含该函数结果的列表。 我不太明白,如何在 haskell 上执行此操作,因为我们这里实际上没有循环和数组。

【问题讨论】:

  • 一旦您有了配对列表,您只需 map 列表中的函数即可。不过,为了得到这对,我相信 Haskell 有一个 partition 函数可以满足你的需求。此外,Haskell 确实在技术上具有循环,只是没有正式的循环语言结构。大多数事情都是通过递归或一些使用递归的抽象来实现的(如map)。
  • 提示:使用zipWith
  • @WillemVanOnsem 出于好奇,[Haskell] 标签是否会收到电话提醒或其他信息?对于 Haskell 问题,您的响应时间通常非常快。
  • 你不能只用zip做这个吗,没关系zipWith?如果您的列表是lst,那么zip (init lst) (tail lst) 应该这样做,不是吗? [显然,如果您的列表可能是空的,您必须小心。]
  • @Carcigenicate:你可以在标签中打开最新的问题。如果您将其固定,某些浏览器(例如 Firefox)会在标题更改时发出通知,仅此而已:)

标签: haskell


【解决方案1】:

您可以尝试以下一些方法来解决此问题。第一步是获取对,第二步是将函数应用于对。完成第一步的一种方法是使用递归函数。现在在 Haskell 列表中使用 []:[1,2,3]1:(2:(3:[])) 的语法糖。所以让我们编写我们的函数:

window [] = []
window [a] = []
window [a,b] = [(a,b)]
window (a:b:r) = (a,b):window (b:r)

我们可以做到这一点的另一种方法是使用函数zip。回想一下,这需要两个列表,将它们的元素配对,并在任一输入结束时结束列表。

window [] = []
window xs = zip xs (tail xs)

第二步是将我们的函数应用于配对。我们可以通过map (uncurry f) 做到这一点。一起来:

onWindow f = map (uncurry f) . window

【讨论】:

    【解决方案2】:

    这里有几种方法可以奏效。

    你可以使用递归:

    mapCons :: (a -> a -> b) -> [a] -> [b]
    -- input has at least two elements
    mapCons f (a0:a1:as) =
      -- use them to compute the head of the output
      f a0 a1 :
      -- reuse the second element to compute the tail of the output
      mapCons f (a1:as)
    -- input has less than two elements, so output is the empty list
    mapCons _ _ = []
    

    或者,zip 将一对列表转换为一对列表:

    λ zip [1..10] ['a'..'z']
    [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j')]
    

    这提供了一种方法来生成列表中的所有连续对,方法是使用自己的尾部压缩列表:

    λ zip [1..10] ['a'..'z']
    [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j')]
    

    然后您可以使用map 在列表中的每一对上运行您的函数

    λ map (\(a,b) -> 10*a + b) $ zip [0..9] (tail [0..9])
    [1,12,23,34,45,56,67,78,89]
    

    这是一个足够常见的模式,有一个结合mapzip的函数:zipWith

    λ :t zipWith
    zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    λ zipWith (\a b -> 10*a + b) [0..9] (tail [0..9])
    [1,12,23,34,45,56,67,78,89]
    

    【讨论】:

    • 您可以进一步缩短:(zipWith f <*> tail) [0..9].
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多