Search code examples
scalafor-loopbreakfor-comprehension

Scala: call a function to check if value exists, if not, create and add to list once


Suppose I have these classes: Foo(id: String) and Bar(fooId: String)

I have a list of Foo objects, I want to create a list of Bar objects according to the id in the Foo objects. If a bar exists in the list I don't want to be created again and added to the list. I can use Set to solve this problem but I don't like it that way. It is just not right.

def createBars() = {
  var barList = List[Bar]()
  for {
    f ← fooList
    bar = findOrCreateBar(f, barList)
    barList = barList:+bar  //error

  } yield bar
}

def findOrCreateBar(f: Foo, barList: List[Bar]): Bar = {
  barList match {
    case Nil ⇒
      Bar(f.id)
    case _ ⇒
      val bars = for {
        bar ← barList
        if f.id == bar.id
      } yield bar

      if (bars.isEmpty) {
        Bar(f.id)
      } else {
        bars.head
      }
  }
}

I have a few issues:

first the code above does not work because I get compile error in barList:+bar in createBars. The :+ cannot be resolved! Also the compiler says that the var for declaring the barList could be val! So it seems that the compiler does not see the barList in the barList = barList:+bar as a list!

second If I replace the var of barList to val I can't reassign the changed list to barList

third I am using for comprehension in the createBars because I thought I have no other choice to return the barList. Using annotations and such just for a break in a regular foor-loop is not a nice idea, imho!

Please help!


Solution

  • What about

    fooList.distinct.map(foo=>Bar(foo.id))
    

    It is simple, efficient and keep the original list order.