Swap two elements in a list by its indices

后端 未结 9 1991
暗喜
暗喜 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 09:15

    I really like @dfeuer 's solution. However there's still room for optimization by way of deforestation:

    swap' :: Int -> Int -> [a] -> [a]
    swap' first second lst = beginning $ [y] ++ (middle $ [x] ++ end)
      where
        (beginning, (x : r)) = swapHelp first lst
        (middle, (y : end)) = swapHelp (second - first - 1) r
    
    swapHelp :: Int -> [a] -> ([a] -> [a],[a])
    swapHelp 0 l     = (    id , l)
    swapHelp n (h:t) = ((h:).f , r) where
                       (     f , r) = swapHelp (n-1) t
    
    0 讨论(0)
  • 2020-12-30 09:16

    This is a strange thing to do, but this should work, aside from the off-by-one errors you'll have to fix since I'm writing this on my phone. This version avoids going over the same segments of the list any more times than necessary.

    swap' :: Int -> Int -> [a] -> [a]
    swap' first second lst = beginning ++ [y] ++ middle ++ [x] ++ end
      where
        (beginning, (x : r)) = splitAt first lst
        (middle, (y : end)) = splitAt (second - first - 1) r
    
    swap x y | x == y = id
             | otherwise = swap' (min x y) (max x y)
    
    0 讨论(0)
  • 2020-12-30 09:18

    That's how I solved it:

    swapElementsAt :: Int -> Int -> [a] -> [a]
    swapElementsAt a b list = list1 ++ [list !! b] ++ list2 ++ [list !! a] ++ list3
        where   list1 = take a list;
                list2 = drop (succ a) (take b list);
                list3 = drop (succ b) list
    

    Here I used the convention that position 0 is the first. My function expects a<=b.

    What I like most in my program is the line take a list.

    Edit: If you want to get more such cool lines, look at this code:

    swapElementsAt :: Int -> Int -> [a] -> [a]
    swapElementsAt a another list = list1 ++ [list !! another] ++ list2 ++ [list !! a] ++ list3
        where   list1 = take a list;
                list2 = drop (succ a) (take another list);
                list3 = drop (succ another) list
    
    0 讨论(0)
提交回复
热议问题