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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.