Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a new list inside foreach in scala

Tags:

scala

I am newbie to scala and just trying out stuff, below is what I am trying

scala> var col  = List[String]()
col: List[String] = List()

scala> List("a", "b", "c").foreach(x => x :: col)

scala> println(col)
List()

Actually, I was expecting col to contain a,b,c, what am I missing?

like image 549
samadhi000 Avatar asked Dec 10 '22 12:12

samadhi000


2 Answers

You need an assignment in the foreach

scala> var col  = List[String]()
col: List[String] = List()

scala> List("a", "b", "c").foreach(x => {col = x :: col})

scala> col
res0: List[String] = List(c, b, a)

The operation x :: col simply returns a new list consisting of the element x prepended to col, the original col is not changed. You would need to reassign col to this newly generated list.

Note however that this would not typically be considered idiomatic Scala since you are using side-effects.

like image 169
evan.oman Avatar answered Dec 31 '22 03:12

evan.oman


The :: method on list does not add anything to the list, it creates a new list with the value prepended to it, you are discarding this new list instead of reassigning it to col. x => col = x :: col will add each element of your list to col. Note that col will then be List("c","b","a"), the order is reversed because you are pre-pending the elements to col.

Note that foreach returns nothing and is designed for side-effecting operations. If you simply want to transform a collection or load elements into another collection there are better methods to use.

For your specific operation, the most appropriate method is foldRight which iterates elements in reverse order, right-to-left. We want to iterate in reverse here because when you prepend elements to a list one at a time the order gets reversed.

val col = List("a", "b", "c").foldRight(List[String]())((x, acc) => x :: acc) will produce a List("a", "b", "c"). This has the advantage that we no longer need to use var to declare a mutable variable, and in fact we don' to need to declare our list ahead of time at all.

note, we could have used some special syntax to save some typing

val col = List("a", "b", "c").foldRight(List[String]())(_ :: _)

The underscores give us a shorter syntax to write function literals, I'll leave up to you to decide if it's more clear or not.

like image 43
puhlen Avatar answered Dec 31 '22 01:12

puhlen