3

I'm just learning Haskell and I would like to make a "shuffle" function that shuffles together two lists, alternating until one runs out. So, shuffle "abc" "defgh" would return "adbecfgh". Or shuffle "abc" "" returns "abc".

So far I have:

shuffle xs ys = concatMap (\(x,y) -> [x,y]) (zip xs ys)

The problem is that it's only shuffling the lists for the length of the shortest list and not including the rest of the longer list. So shuffle "abc" "defgh" returns "adbecf" rather than "adbecfgh".

Can anyone help me find a better approach to this?

fia928
  • 143
  • 3
  • 10
  • Also [interleave list of lists](http://stackoverflow.com/questions/14186433/interleave-list-of-lists-in-haskell) is similar, yet a bit more general. – phadej Feb 11 '15 at 07:42

2 Answers2

9

You could simply provide a pointwise definition:

shuffle :: [a] -> [a] -> [a]
shuffle [] ys = ys
shuffle xs [] = xs
shuffle (x:xs) (y:ys) = x : y : shuffle xs ys

Every zip* method in Prelude or Data.List won't work, as they will take only the length of the shorter list.

Zeta
  • 103,620
  • 13
  • 194
  • 236
7

Another, slightly shorter, way to do it pointwise, as Zeta suggested:

shuffle :: [a] -> [a] -> [a]
shuffle [] ys = ys
shuffle (x:xs) ys = x : shuffle ys xs
dfeuer
  • 48,079
  • 5
  • 63
  • 167