繁体   English   中英

Haskell函数用于交换列表中的每个第二个元素

[英]Haskell function to swap every second element in a list

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

示例输出应如下所示:

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

到目前为止我所拥有的是什么

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

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

您需要一次抓取2个元素:

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

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

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

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]

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

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

但是请注意, headtail的使用是不必要的,并且模式匹配可以使这里的事情变得更加清洁。

import Data.Function(on)

swap = map snd . concatMap reverse . groupBy ((==) `on` fst) . zip (cycle "aabb")

不要把我的解决方案太严肃,我只是想改善我的Haskell-Foo ......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM