我有一个列表a,
let a = ["#","@","#","#"]
Run Code Online (Sandbox Code Playgroud)
如何旋转这@两个空格,以便它最终像这样?
["#","#","#","@"]
Run Code Online (Sandbox Code Playgroud)
我认为这可行,
map last init a
Run Code Online (Sandbox Code Playgroud)
但也许语法必须不同,因为map只能用于一个函数?
dav*_*420 62
为了完整起见,一个适用于空列表和无限列表的版本.
rotate :: Int -> [a] -> [a]
rotate _ [] = []
rotate n xs = zipWith const (drop n (cycle xs)) xs
Run Code Online (Sandbox Code Playgroud)
然后
Prelude> rotate 2 [1..5]
[3,4,5,1,2]
Run Code Online (Sandbox Code Playgroud)
MGw*_*nne 25
使用该cycle函数的简单解决方案,它创建输入列表的无限重复:
rotate :: Int -> [a] -> [a]
rotate n xs = take (length xs) (drop n (cycle xs))
Run Code Online (Sandbox Code Playgroud)
然后
> rotate 2 ["#","@","#","#"]
["#","#","#","@"].
Run Code Online (Sandbox Code Playgroud)
aug*_*tss 17
为什么让它变得复杂?
rotate n xs = bs ++ as where (as, bs) = splitAt n xs
Run Code Online (Sandbox Code Playgroud)
azt*_*tek 14
rotate :: Int -> [a] -> [a]
rotate = drop <> take
Run Code Online (Sandbox Code Playgroud)
因为instance Monoid b => Monoid (a -> b)上面的例子相当于
rotate n = drop n <> take n
Run Code Online (Sandbox Code Playgroud)
这又相当于
rotate n xs = drop n xs <> take n xs
Run Code Online (Sandbox Code Playgroud)
因为instance Monoid d => Monoid (c -> d)实例,它等价于
rotate n xs = drop n xs ++ take n xs
Run Code Online (Sandbox Code Playgroud)
因为instance Monoid [e]实例(带有b ~ c -> d和d ~ [e])。
(好吧,Semigroup已经足够了,但这里是一样的)。
我是Haskell的新手,所以MGwynne的答案很容易理解。结合建议使用另一种语法的注释,我试图使其在两个方向上都能正常工作。
rotate :: Int -> [a] -> [a]
rotate n xs = take lxs . drop (n `mod` lxs) . cycle $ xs where lxs = length xs
Run Code Online (Sandbox Code Playgroud)
因此rotate (-1) [1,2,3,4],您得到的结果与相同rotate 3 [1,2,3,4]。
我以为我必须添加它,因为dropping少于0个元素不会执行任何操作,因此我的首选答案给出了带有错误负值的“错误”(至少令人困惑)结果n。
此解决方案的有趣之处在于,它结合了负旋转的“完整性”和对空列表的处理。感谢Haskell的懒惰,它也为给出了正确的结果rotate 0 []。