jerome
jerome

Reputation: 2089

Concatenate multiple list

I would like to know how to concatenate several list using a loop. Here is an example of what I'm trying to do:

object MyObj {
  var objs = Set (
    MyObj("MyObj1", anotherObjList),
    MyObj("MyObj2", anotherObjList)
  )

  val list = List.empty[AnotherObj]
  def findAll = for (obj <- objs) List.concat(list, obj.anotherObjList)
}

I would like the function findAll to concatenate lists from object of the set objs.

Upvotes: 3

Views: 868

Answers (3)

Markus1189
Markus1189

Reputation: 2869

In your code example, you are using a val list which cannot be reassigned. When you do List.concat(list, obj.anotherObjList) you are creating a new list that concats the empty list to the current obj's anotherObjList, but the result is never used, so list will still be empty after the execution of the for-loop.

If you really need to use a imperative for-loop, either use an immutable collection and assign it to a var which can be reassigned from the for-loop's body or use a mutable collection:

object MyObj {
  var objs = Set(
    MyObj("MyObj1", anotherObjList),
    MyObj("MyObj1", anotherObjList),
  )

  def findAllLoop1 = {
    var list = List.empty
    for (obj <- objs) list = list ++ obj.anotherObjList
    list
  }

  def findAllLoop2 = {
    val buf = collection.mutable.ListBuffer[Int]() // replace Int with your actual type of elements
    for (obj <- objs) buf ++= obj.anotherObjList
  }
}

But If you don't have to use a imperative loop for some reason, I would strongly suggest to use a functional alternative:

object MyObj {
  var objs = Set(
    MyObj("MyObj1", anotherObjList),
    MyObj("MyObj1", anotherObjList),
  )

  def findAll = 
    objs.flatMap(_.anotherObjList) // if Set as return type is okay

  def findAll: List[Int] = 
    objs.flatMap(_.anotherObjList)(collection.breakOut)  // if elements are of type Int and you want to get a List at the end, not a Set
}

Upvotes: 1

Luka Jacobowitz
Luka Jacobowitz

Reputation: 23502

Use reduce

Something like this:

objs.reduce((a,b) => a.anotherObjList ++ b.anotherObjList)

Or if the Set can be empty, use foldLeft:

objs.foldLeft(List.empty[AnotherObj],(a,b) => a.anotherObjList ++ b.anotherObjList)

Upvotes: 1

Jean-Philippe Pellet
Jean-Philippe Pellet

Reputation: 59994

Try this:

objs.flatMap(_.anotherObjList)

It doesn't use a for, but that's probably the most concise and readable way to do it in Scala.

Upvotes: 5

Related Questions