Swap two elements in a list by its indices

后端 未结 9 2025
暗喜
暗喜 2020-12-30 08:25

Is there any way to swap two elements in a list if the only thing I know about the elements is the position at which they occur in the list.

To be more specific, I a

9条回答
  •  温柔的废话
    2020-12-30 08:58

    There are several working answers here, but I thought that a more idiomatic haskell example would be useful.

    In essence, we zip an infinite sequence of natural numbers with the original list to include ordering information in the first element of the resulting pairs, and then we use a simple right fold (catamorphism) to consume the list from the right and create a new list, but this time with the correct elements swapped. We finally extract all the second elements, discarding the first element containing the ordering.

    The indexing in this case is zero-based (congruent with Haskell's typical indexes) and the pointers must be in range or you'll get an exception (this can be easily prevented if you change the resulting type to Maybe [a]).

    swapTwo :: Int -> Int -> [a] -> [a]
    swapTwo f s xs = map snd . foldr (\x a -> 
            if fst x == f then ys !! s : a
            else if fst x == s then ys !! f : a
            else x : a) [] $ ys
        where ys = zip [0..] xs
    

    And a single liner, doing the swap in just one pass (combining the functionality of the foldr and map into a zipWith):

    swapTwo' f s xs = zipWith (\x y -> 
        if x == f then xs !! s
        else if x == s then xs !! f
        else y) [0..] xs
    

提交回复
热议问题