在Haskell中旋转列表

时间:2013-05-04 20:42:26

标签: haskell

我定义了一个列表a

let a = ["#","@","#","#"]

如何旋转@两个空格,以便它最终结束?

["#","#","#","@"]

我认为这可行,

map last init a

但也许语法必须不同,因为map只能用于一个函数?

8 个答案:

答案 0 :(得分:58)

为了完整起见,这个版本适用于空列表和无限列表。

rotate :: Int -> [a] -> [a]
rotate _ [] = []
rotate n xs = zipWith const (drop n (cycle xs)) xs

然后

Prelude> rotate 2 [1..5]
[3,4,5,1,2]

答案 1 :(得分:24)

使用cycle函数的简单解决方案,它会创建无限重复的输入列表:

rotate :: Int -> [a] -> [a]
rotate n xs = take (length xs) (drop n (cycle xs))

然后

> rotate 2 ["#","@","#","#"]
["#","#","#","@"].

答案 2 :(得分:17)

为什么要让它变得复杂?

rotate n xs = bs ++ as where (as, bs) = splitAt n xs

答案 3 :(得分:3)

我对haskell很新,所以MGwynne's answer很容易理解。结合comment suggesting an alternative syntax,我试图让它在两个方向都有效。

rotate :: Int -> [a] -> [a]
rotate n xs = take lxs . drop (n `mod` lxs) . cycle $ xs where lxs = length xs

因此,rotate (-1) [1,2,3,4]会为您提供与rotate 3 [1,2,3,4]相同的结果。

我认为我必须添加这个,因为drop ping不到0个元素什么都不做,所以我的首选答案是"错误" (至少令人困惑)结果为n参数的负值。

这个解决方案的有趣的部分是它结合了"完整性"用于处理空列表的负旋转。感谢Haskell的懒惰,它也为rotate 0 []提供了正确的结果。

答案 4 :(得分:2)

初学者尝试:

myRotate :: Int -> [String] -> [String]
myRotate 0 xs = xs
myRotate n xs = myRotate (n-1) (last xs : init xs)

答案 5 :(得分:1)

对于大型列表来说不是很快,但足够:

rotate :: Int -> [a] -> [a]
rotate n xs = iterate rot xs !! n
  where
    rot xs = last xs : init xs

例如:

> rotate 2 ["#","@","#","#"]
["#","#","#","@"]

答案 6 :(得分:0)

rotate :: Int -> [a] -> [a]
rotate n xs = drop k xs ++ take k xs
                where k = length xs - n

此功能向右旋转n个位置。

答案 7 :(得分:0)

rotate :: Int -> [a] -> [a]
rotate = drop <> take