【问题标题】:How to split a list into two using even and odd positions?如何使用偶数和奇数位置将列表分成两部分?
【发布时间】:2021-09-28 20:26:03
【问题描述】:

我正在尝试根据列表中的索引/位置将列表拆分为偶数和奇数。例如对于列表[2,3,6],结果应该是even = [2,6]odd = [3]

我想使用不使用列表推导的方法——一次匹配两个元素,将一个放在偶数列表中,一个放在赔率列表中。

但我不确定让它工作的语法。我知道如何从逻辑上讲,但我在语法上苦苦挣扎。这是我目前所拥有的:

splitOnPos :: [a] -> ([a], [a])
splitOnPos [] = ([], [])
splitOnPos (x1:x2:xs) = (odds, evens)   
    where 
        odds  = x1 : splitOnPos xs
        evens = x2 : splitOnPos xs

我收到以下关于类型的错误:

* Couldn't match expected type `[a]' with actual type `([a], [a])'
    * In the second argument of `(:)', namely `splitOnPos xs'
      In the expression: x2 : splitOnPos xs
      In an equation for `evens': evens = x2 : splitOnPos xs

【问题讨论】:

  • @MichaelLitchard 我刚刚编辑了它与类型和发生的错误有关的错误,因为我无法弄清楚语法
  • @httpsissecure,你还没有给minimal reproducible example
  • @httpsissecure,显然你还没有阅读我发布的链接。
  • @httpsissecure,其中的所有代码只有 5 行左右?太好了,split 是什么? Prelude里没有这种东西,你从哪里弄来的?
  • @httpsissecure 我建议给每个值一个明确的类型,它会引导你找到解决方案。这样做,而不是让别人为你找到问题,你会得到更深刻的理解。

标签: haskell


【解决方案1】:

你快到了。应该是的

splitOnPos :: [a] -> ([a], [a])
splitOnPos [] = ([], [])
splitOnPos (x1:x2:xs) = (x1:odds, x2:evens)   
    where 
        (odds, evens) = splitOnPos xs

正如错误消息提醒您的那样,该函数返回一个元组(一对)列表,而不仅仅是一个您可以使用 (:) 任何东西的列表。

所以我们将元组放入,并将两个头元素中的每一个添加到相应的列表中,再次将结果重新打包为一对,因此类型适合:

 ( x1:odds        <--       ( odds
   ,                          ,           <---- recursive call
   x2:evens )     <--         evens )

您还需要在这里写一个等式,以便涵盖所有情况。现在你只处理空列表的情况,以及包含两个或更多元素的列表。

未处理单例列表情况。结果它只适用于长度均匀的列表:

> splitOnPos [0..9]
([0,2,4,6,8],[1,3,5,7,9])

> splitOnPos [0..10]
([0,2,4,6,8*** Exception: <interactive>:(574,1)-(577,37):
 Non-exhaustive patterns in function splitOnPos

【讨论】:

  • 对于这个特定问题还有一个非常酷的技巧,它可以让您一次在一个元素上进行模式匹配,而不是两个。 (这也意味着它将适用于单元素列表,而不是像这个那样崩溃。)splitOnPos (x:xs) = (x:evens, odds) where (odds, evens) = splitOnPos xs
  • @DanielWagner 这是一个不错的老歌好歌,甚至可以扩展到三元组等,但 OP 想了解 他们的 代码以及如何修复它所以我专注于那个。 :)
猜你喜欢
  • 1970-01-01
  • 2012-07-26
  • 2021-06-18
  • 1970-01-01
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多