Home > Back-end >  expand list of lists by adding element once to every list
expand list of lists by adding element once to every list

Time:11-18

I implement function which adds an element once to every list of a list.

example:

f :: a -> [[a]] -> [[[a]]]
f 7 [[1],[2],[3]]
[[[7,1],[2],[3]],[[1],[7,2],[3]],[[1],[2],[7,3]]]

I start with this solution:

f :: a -> [[a]] -> [[[a]]]
f e xs = ((\n -> (\(x,l)-> if x==n then e:l else l) <$> zip [1..] xs)  <$> [1..length xs])

Can you please provide some more nice implementations of this function?

CodePudding user response:

You can implement this with recursion. As base case we consider an empty list:

f _ [] = []

for non-empty lists (x:xs) we can use the first item, which is the first sublist. We thus can produce a list where we prepend the first sublist x with the element e, followed by the remaining items xs, so (e:x) : xs is the first item. For the remaining items we recurse on the tail of the list xs and will for each sublist prepend this with the sublist x:

f e (x:xs) = ((e:x) : xs) : map (x:) (f e xs)

so putting these together gives us:

f :: a -> [[a]] -> [[[a]]]
f _ [] = []
f e (x:xs) = ((e : x) : xs) : map (x:) (f e xs)

CodePudding user response:

Write splits which gives all possible ways of splitting a list

splits :: [a] -> [([a], [a])]
splits xs = zip (inits xs) (tails xs)

for example

> splits "abc"
[("","abc"),("a","bc"),("ab","c"),("abc","")]

and using it write a function that operates on each element of a list

onEach :: (a -> a) -> [a] -> [[a]]
onEach f xs = [ys    f z : zs | (ys, z:zs) <- splits xs]

like this

> onEach toUpper "abc"
["Abc","aBc","abC"]

and now f is just

f :: a -> [[a]] -> [[[a]]]
f x = onEach (x:)
  • Related