1

I want to split a list on 1 element and take the rest of the list in the second of the tuple and return that.

like this: *> split [1,2,3,2] gives [(1,[2,3,2]),(2,[1,3,2]),(3,[1,2,2]),(2,[1,2,3])]

I tried some code like this but it keeps giving me errors. Can someone help me out with this?

split :: [Int] -> [(Int,[Int])]
split [] = []
split (x:xs) = (map (x:) (map snd (split xs))) ++ [(x,[])] 

Thx!

1
  • 3
    1. Always add the error you encounter. 2. You cannot map (x:) onto [(Int, [Int])], since (Int, [Int]) is not a list. 3. If you only use xs in the recursive call, you would always forget the start of the list. 4. Try to be more verbose. Write a function that, for a given index, splits the indexed value and the rest. Use this together with zipWith [0..] for a first prototype. Commented Dec 23, 2015 at 16:26

3 Answers 3

2

My answer to an older question goes via an answer to this one.

I call this operation picks because it tells you all the ways to pick one out of a list (seen as a bag).

picks :: [x] -> [(x, [x])]
picks [] = []
picks (x : xs) = (x, xs) : [(y, x : ys) | (y, ys) <- picks xs]

It's standard issue zipper-wrangling kit, about which I've written at great length in other answers, such as the one linked above, and this one, for the works.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use inits and tails from Data.List:

{-# LANGUAGE ParallelListComp #-}
split xs = [(x, pre ++ post) | pre <- inits xs | x:post <- tails xs]

or, if you don't like ParallelListComp:

split xs = [(x, pre ++ post) | (pre, x:post) <- zip (inits xs) (tails xs)]

Comments

1

This is possible with a list comprehension. Using zip you can create a tuple with an index and each element, then you can consturct a new tuple with your element and the original list minus the element at that index

splitter :: [a] -> [(a, [a])]
splitter xs = [(x, removeN n xs) | (n, x) <- zip [0..] xs]

That's using a function to remove the nth element

removeN :: Int -> [a] -> [a]
removeN n xs = take n xs ++ drop (n + 1) xs

example

*Main> splitter [1..4]
[(1,[2,3,4]),(2,[1,3,4]),(3,[1,2,4]),(4,[1,2,3])]

3 Comments

nice but this has quadratic complexity because of take/drop on each iteration
@maxtaldykin, that actually can't be avoided. The "pre-hole" parts of the result lists can't share any structure with each other.
However, using splitAt should give better constant factors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.