antonkw
antonkw

Reputation: 33

Scala flatten list of String and List[String]

Need some help with Scala flatten.

I have a list of String and List[String].

Example: List("I", "can't", List("do", "this"))

Expecting result: List("I", "can't", "do", "this")

I've done a lot of experiments, and most compact solution is:

val flattenList = list.flatten {
  case list: List[Any] => list
  case x => List(x)
}

But it seems very tricky and hard to understand. Any suggestions for more naive code?

Thanks.

Upvotes: 2

Views: 1559

Answers (2)

Dima
Dima

Reputation: 40500

What's "tricky and hard to understand" is your mixing elements of different type in the same list. That's the root cause of your problem. Once you have that, there is no way around having to scan the list, and inspect the type of each element to correct it, and your solution to that is as good as any (certainly, better, than the one, suggested in the other answer :)).

I would really rethink the code path that leads to having a heterogeneous list like this in the first place though if I were you. This is not really a good approach, because you subvert the type safety this way, and end up with a List[AnyRef], that can contain ... well, anything.

Upvotes: 3

yǝsʞǝla
yǝsʞǝla

Reputation: 16412

I don't think you can avoid having to deal with 2 cases: single element vs list. One way or another you would have to tell your program what to do. Here is a more general implementation that deals with a list of any depth:

def flattenList(xs: List[Any]): List[Any] =
  xs match {
    case Nil => Nil
    case (ys:List[_]) :: t => flattenList(ys) ::: flattenList(t)
    case h :: t => h :: flattenList(t)
  }

Example:

scala> flattenList(List("I", "can't", List("do", "this")))
res1: List[Any] = List(I, can't, do, this)

scala> flattenList(List("I", "can't", List("do", List("this", "and", "this"))))
res2: List[Any] = List(I, can't, do, this, and, this)

This does not look very type safe though. Try to use a Tree or something else.

Upvotes: 1

Related Questions