【问题标题】:Haskell function to swap every second element in a listHaskell 函数交换列表中的每一秒元素
【发布时间】:2011-11-13 19:28:44
【问题描述】:

我想知道如何在 Haskell 中交换列表的第二个元素。

示例输出应如下所示:

swap [1,2,3,4,5]  
[2,1,4,3,5]

到目前为止我所拥有的是

swap :: [a] -> [a]  
swap [] = []  
swap (x:xs) = head xs : [x]

但这只会交换前两个元素,当我尝试加载包含该函数的文件时,我为使函数递归所做的任何尝试都会导致错误。如何使其递归?

【问题讨论】:

  • 展示你的尝试和它导致的错误怎么样?
  • 我想做的是 swap (x:xs) = head xs : [x] swap xs 。尝试加载文件时的错误是 "haskell.hs:3:25: The function [x]' is applied to two arguments, but its type [a]' has none 在(:)', namely [x] 的第二个参数中交换 xs' 在表达式中:head xs : [ x] swap xs 在 `swap' 的等式中:swap (x : xs) = head xs : [x] swap xs 失败,加载模块:无。"

标签: list haskell recursion


【解决方案1】:

你需要一次抓取两个元素:

swap [] = []
swap (x:y:rest) = y:x:(swap rest)
swap [x] = [x]

最后一行需要允许奇数长度的列表 - 它匹配长度正好为 1 的列表,因此它不会与其他两种情况(长度为 0,长度为 2 或更多)中的任何一种重叠。

【讨论】:

  • (x:y:rest) 案例之后,空和单元素模式可以更简洁地表示为swap other = other
  • 感谢您的帮助。我已经弄清楚如何通过添加 swap [x] = [x] 使您的代码适用于奇数大小的列表
  • @Chuck:是的,但是你必须把那个案例放在最后,因为它与另一个案例重叠。当案例不相交时,我会感觉更舒服,因为从那时起它们可以按任何顺序排列(也许那是糟糕的风格?)
  • @j_random_hacker:不幸的是,我的风格仲裁者帽子在清洁工身上,但就我个人而言,我更看重简洁而不是“能够随机重新排列线条并让它发挥作用”。在 Haskell 代码中,在你的正常情况下有一个包罗万象是很正常的,所以我认为它不会让任何人失望。
【解决方案2】:

除了其他相当出色的回复之外,这里有一个使用一些非常方便的库的解决方案。首先,安装split,它提供了许多非常好的拆分列表的方法。我们解决这个问题的策略是首先将您的列表分成大小为 2 的块,然后交换每个块,然后将结果连接回一个平面列表。下面是 key 函数的工作原理:

Prelude Data.List.Split> chunk 2 [1..11]
[[1,2],[3,4],[5,6],[7,8],[9,10],[11]]

要交换每个块的元素,我们可以简单地调用reverse。所以最终的结果是:

Prelude Data.List.Split> let swap = concat . map reverse . chunk 2
Prelude Data.List.Split> swap [1..5]
[2,1,4,3,5]

【讨论】:

    【解决方案3】:

    @j_random_hacker 的解决方案更好,但是,如果你想看到你的实现完成,你可以试试这个:

    swap [] = []
    swap (x:[]) = [x]
    swap (x:xs) = head xs : x : (swap $ tail xs)
    

    但是请注意,headtail 的使用是不必要的,而模式匹配可以使这里的内容更加简洁。

    【讨论】:

      【解决方案4】:
      import Data.Function(on)
      
      swap = map snd . concatMap reverse . groupBy ((==) `on` fst) . zip (cycle "aabb")
      

      不要把我的解决方案看得太认真,我只是想改进我的 Haskell-Foo...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多