您好我一直在找答案,但找不到答案。假设我们有一个类似[1,10,4,5,3]
的列表,如何将5向左移动,以便此列表变为[1,10,5,4,3]
。
我尝试swapElementsAt
找到该元素的索引,但看起来非常不足。
答案 0 :(得分:1)
swapElementsAt :: Int -> [a] -> [a]
swapElementsAt n list = let (beg, a:b:rest) = splitAt (n-1) list in beg ++ b:a:rest
就像
一样λ> swapElementsAt 3 [1,10,4,5,3]
[1,10,5,4,3]
答案 1 :(得分:0)
如果您要从左到右遍历输入列表,查看列表开头的非常本地附近(如果您可以轻松地模式匹配的话),请考虑如何编写此函数?
最直接的方法是对前两个元素进行模式匹配,并检查第二个元素是否与您的模式匹配。如果是这样,只需通过交换这些元素并附加列表的其余部分来构建一个新列表,否则,递归遍历其余部分。
在代码中:
swapElem :: Eq a => a -> [a] -> [a]
swapElem e (x:y:xs) | y == e = y : x : xs
swapElem e (x:xs) = x : swapElem e xs
swapElem _ [] = []
第一个模式仅在列表中至少有两个元素时匹配,第二个元素等于所需的元素。如果元素较少或第二个元素不正确,则它将落入第二个模式,匹配任意非空列表并在列表的其余部分调用swapElem
。第三种模式是提供空输入列表的基本递归情况。
请注意,此代码仅更改目标元素的第一次出现:
Prelude> swapElem 5 [1, 10, 4, 5, 3]
[1,10,5,4,3]
Prelude> swapElem 5 [1, 10, 5, 4, 5, 3]
[1,5,10,4,5,3]
你如何改变它以便左移所有5
?
此外,答案取决于您的输入究竟是什么。 @Scarabyte的答案考虑了你给出目标元素位置的情况,而这种方法则考虑了你想要向左移动的元素。