views:

159

answers:

2

I want to define a function replicate to replicate a list of numbers by its value using only list comprehension, for example:

replicate [5,1,3,2,8,1,2]
output: [5,5,5,5,5,1,3,3,3,2,2,8,8,8,8,8,8,8,8,1,2,2]

I know this would be easy to use the 'replicate' built in function but only list comprehension is allow, how can I do this?

THANKS!

+7  A: 

Neat little problem. I solved it like this.

replicate list = [ a | a <- list, _ <- [1..a]]

Prelude> replicate [5,1,3,2,8,1,2]

[5,5,5,5,5,1,3,3,3,2,2,8,8,8,8,8,8,8,8,1,2,2]

It takes each value in the list, creates that many copies of itself, and then moves to the next value.

sabauma
it works, but I have no idea how. it seems 'b' doesnt have anything to do with 'a' yet it makes it have multiple copies. interesting on how this works.
Linda Cohen
Tip: You can read simple list comprehensions a lot like imperative loops that accumulate values onto the end of a list. `a <- list` says "loop over each element of `list`" and `b <- [1..a]` is a loop inside that loop saying "loop with `b` going from 1 to `a`". The `a` at the beginning says accumulate `a` onto the end of the list each time around.
I'd suggest using _ instead of b to make it clear that you don't actually care about the value of b.
sepp2k
To add to user207442, if we have a list that goes `[x|exp]`, the list will contain all the `x` for which exp is true. If `exp` contains multiple elements (like here, seperated with comma), the *cross product* is used. `a <- list, b <- [1..a]` means taking all combinations of `a` (being one element of `list`) and `b`. Since `b` contributes with `a` number of elements, we end up with `a` times `a` elements.
Svend
+4  A: 

For kicks:

import Control.Monad
import Control.Monad.Instances

repList = concatMap $ join replicate
trinithis