我正在尝试编写一个函数,它接受列表的最后一个元素并将该元素放在列表前面。我需要这个功能运行n次。
执行翻转的功能。
flipBack' :: [a] -> [a]
flipBack' xs = [last xs] ++ reverse (drop 1 (reverse xs))
所以上面就像是下层函数的辅助函数,它接受初始字符串以及它需要运行上述函数的次数。
rotate :: String -> Int -> String
rotate xs n = flipBack' xs
因此,例如,如果n为3,则rotate函数应执行以下操作:
flipBack'(flipBack'(flipBack' xs))
看起来迭代应该以某种方式在这里使用,但我在这里实现它有困难,因为我不完全理解它是如何工作的。
答案 0 :(得分:4)
您正在寻找的功能是iterate
e.g。
> (iterate flipBack' [1..3])!!3
[1,2,3]
所以你可以写
rotate xs n = (iterate flipBack' xs)!!n
请注意iterate
也很容易定义自己
iterate f x = x : iterate f (f x)
答案 1 :(得分:4)
这不是实现rotate
功能的好方法! flipBack'
是O(length xs)
,您正在迭代它;这非常昂贵。你怎么能做得更好?
首先请注意,执行flipBack'
length xs
次会回复xs
。因此,您可以先减少n
。
rotate n xs = rotate' (lenx - n `mod` lenx) xs where
lenx = length xs
好的,现在我们如何rotate'
?分裂!
rotate' shift xs = end ++ beginning where
(beginning, end) = splitAt shift xs
如果n
远小于列表的长度,则上述遍历列表以在实际生成任何内容之前获取长度的方法是不幸的。如果情况可能如此,那么使用简化的队列遍历列表可能会更好。这种方法对于我在手机上盲目编码来说太复杂了,所以我只想把它留作思考的想法。