我a
定义了一个列表,
let a = ["#","@","#","#"]
我怎样才能旋转这@
两个空间,让它像这样结束?
["#","#","#","@"]
我认为这可能有效,
map last init a
但也许语法必须不同,因为 map 只能与一个函数一起使用?
我a
定义了一个列表,
let a = ["#","@","#","#"]
我怎样才能旋转这@
两个空间,让它像这样结束?
["#","#","#","@"]
我认为这可能有效,
map last init a
但也许语法必须不同,因为 map 只能与一个函数一起使用?
为了完整起见,该版本适用于空列表和无限列表。
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]
使用该cycle
函数的简单解决方案,它创建输入列表的无限重复:
rotate :: Int -> [a] -> [a]
rotate n xs = take (length xs) (drop n (cycle xs))
然后
> rotate 2 ["#","@","#","#"]
["#","#","#","@"].
为什么要复杂化?
rotate n xs = bs ++ as where (as, bs) = splitAt n xs
rotate :: Int -> [a] -> [a]
rotate = drop <> take
由于instance Monoid b => Monoid (a -> b)
上面的实例等价于
rotate n = drop n <> take n
这又相当于
rotate n xs = drop n xs <> take n xs
因为instance Monoid d => Monoid (c -> d)
实例,这相当于
rotate n xs = drop n xs ++ take n xs
因为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
所以rotate (-1) [1,2,3,4]
给你同样的结果rotate 3 [1,2,3,4]
。
我认为我必须添加这个,因为drop
ping 小于 0 的元素什么都不做,所以我的首选答案给出了n
参数为负值的“错误”(至少令人困惑)结果。
这个解决方案的有趣之处在于它结合了负旋转的“完整性”和空列表的处理。由于 Haskell 的懒惰,它也为rotate 0 []
.
初学者尝试:
myRotate :: Int -> [String] -> [String]
myRotate 0 xs = xs
myRotate n xs = myRotate (n-1) (last xs : init xs)
对于大型列表来说不是很快,但足够了:
rotate :: Int -> [a] -> [a]
rotate n xs = iterate rot xs !! n
where
rot xs = last xs : init xs
例如:
> rotate 2 ["#","@","#","#"]
["#","#","#","@"]
rotate :: Int -> [a] -> [a]
rotate n xs = drop k xs ++ take k xs
where k = length xs - n
此函数向右旋转 n 位。