3

I would like to take a list of RawDoc which each have a title and a single version and transform it into a list of Doc which each have a title and all its versions collected together into a list:

case class RawDoc(title:String, version:String)
case class Doc(title:String, versions:List[String])

val rawDocs:List[RawDoc] = List(
  RawDoc("Green Book", "1.1"),
  RawDoc("Blue Book",  "1.0"),
  RawDoc("Green Book", "1"),
  RawDoc("Blue Book",  "2")
)

I would like to start with the above rawDocs and create docs like this:

val docs:List[Doc] = List(
  Doc("Green Book", List("1.1", "1")),
  Doc("Blue Book",  List("1.0", "2"))
)

Without using for loops how could this be done in Scala?

2 Answers 2

5

This should work:

val docs = rawDocs.
  groupBy(_.title).map{
    case(title, docsWithSameTitle) => 
      Doc(title, docsWithSameTitle.map(_.version))
  }

And if the difference between "Blue Book" and "Blue BooK" is not incidental typo and they should be treated as equal:

val docs = rawDocs.
  groupBy(_.title.toUpperCase).map{
    case(_, docsWithSameTitle) => 
      Doc(docsWithSameTitle.head.title, docsWithSameTitle.map(_.version))
  }
Sign up to request clarification or add additional context in comments.

5 Comments

+1 Nice answer... just a tip: you don't need new for case classes
It's also not ideal to shadow rawDocs.
@TravisBrown: true, refactored to much more descriptive name
Big K was just a typo but having the two answers is instructive.
I prefer the brevity of DCS's answer but this one more closely matches the mental process I would expect to follow.
4
rawDocs.groupBy(_.title).mapValues(_ map (_.version)).map { 
  case (title, versions) => Doc(title, versions) 
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.