1
votes

I have a list of books:

case class Book(name:String,authors:List[String])

val books:List[Book] = List(
                 Book(name="Code in Scala",authors=List("Viny","Vinay")),
                 Book(name="Dance in 30 days",authors=List("Namratha","Namitha")),
                 Book(name="Cook in 30 days",authors=List("Pavan")),
                 Book(name="Gym in 30 days",authors=List("Nisanth","Vinay"))
                 ) 

Now i want to know the books where author name starts with "Vin". I have implemented this in for loop like below:

for(b<-books ; a <- b.authors ; if a.startsWith("Vin")) yield b.name

But i am unable to implement this with higher order function. I tried as below:

books flatMap (b=> b.authors.withFilter(a=>a.startsWith("Vin")).map(x=>x))

This gets me the Name of the authors but i am unable to access the book object.how can i resolve this? Main goal here is to convert/translate the "for loops" into higher order functions(flatmap/filter/map)

3
If you would remove name attribute from the second code example you will get book object. Could you show your code try with higher order function ?? - Pavel

3 Answers

2
votes

I think you are looking for the translation of a for-comprehension to combinators (map, flatmap and filter (withFilter)).

You were almost there. The missing piece is accessing the book object through the right scope:

books.flatMap(b => b.authors.withFilter(a => a.startsWith("Vin")).map(_ => b.name))

The rules are explained in the Scala language Specification (pp 89 of the doc, 97 of the pdf-)

1
votes

Just change the last map to return what you want:

books flatMap (b => b.authors.withFilter(a => a.startsWith("Vin")).map(_ => b.name))

0
votes

I think the flatMap is unnecessary here:

scala> books.filter(_.authors.exists(_.startsWith("Vin"))).map(_.name)
res4: List[String] = List(Code in Scala, Gym in 30 days)