Reputation: 1071
I'm trying to solve problem 12 taken from here
To summarize, given a list of tuples:
List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e))
the result should be a list containing each element in _2 repeated _1 times
The result would be List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
This is my attempt (see code online)
object P12 extends App {
val ls2 = List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e))
println(ls2)
println(decode(ls2))
def decode[A] (list: List[(Int,A)]): List[A] = {
list.foldLeft(List[A]()) { (result, elem) => for ( n <- 1 to elem._1) result :+ elem._2 }
}
}
I get the following error:
Main.scala:9: error: type mismatch;
found : Unit
required: List[A]
list.foldLeft(List[A]()) { (result, elem) => for ( n <- 1 to elem._1) result :+ elem._2 }
how to fix this?
Upvotes: 0
Views: 81
Reputation: 20405
This recursive function denotes (or lists) the semantics concisely in two cases,
def decode( xs: List[(Int,Symbol)] ): List[Symbol] = xs match {
case Nil => Nil
case (x :: xss) => List.fill(x._1)(x._2) ++ decode(xss)
}
An empty list results in an empty list, else for the head element of a non empty list, expand it into a list of repeated elements and prepend it to the rest of the decoded list.
Upvotes: 1
Reputation: 10882
Your for
cycle does nothing, are you are using it in imperative way with immutable collection. On each iteration you create new collection from result
with appended element and then just discard it. The result of your for
is Unit
, hence the error.
The correct functional way to perform your task is this:
def decode[A] (list: List[(Int,A)]): List[A] = {
list.foldLeft(List[A]()) { case (result, (count, el)) =>
result ::: (1 to count).map(_ => el).toList
}
}
UPD: Also please note, that append operation on List
takes linear time, so the whole decode
becomes O(n2).
There is more efficient and concise way to perform your task, using flatMap
:
def decode[A](list: List[(Int, A)]): List[A] =
list.flatMap { case (count, el) => (1 to count).map(_ => el) }
Upvotes: 1
Reputation: 12214
Use List.fill
and a flatMap
:
val l = List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e))
l.flatMap { t => List.fill(t._1)(t._2) }
Upvotes: 3