简体   繁体   中英

Scala: how to append to a Seq

I am struggling with the following piece of code:

type DB = Map[Int, Seq[String]]
var grades: DB = Map.empty
def add(name: String, grade: Int) = {
  var names: Seq[String] = Seq(name)
  if(grades isDefinedAt grade) {
    names = names ++ grades(grade)
  }
    grades += (grade -> names)
}

When I call the "add" method, as follow:

add(2, "Mike")
add(2, "Michelle")
add(2, "John")

I would expect grades to be (2, Seq(Mike, Michelle, John)) but, instead, it contains only the last addition (2, John) .

How can I solve that?

Thanks!!!

If you want to do the same in more Scala way (no side effects, pure functional), take a look to this:

type DB = Map[Int, Seq[String]]

def add(db: DB, name: String, grade: Int): DB = {
  db.get(grade) match {
    case Some(seq) => // key exists, let's update the value
      val newSeq = seq :+ name  // create new sequence
      db.updated(grade, newSeq)
    case None =>      // key does not exist, let's add new key
      db + (grade -> Seq(name))
  }
}

val db: DB = Map.empty

val db1 = add(db, name = "A", grade = 1)
println(s"db1: $db1")

val db2 = add(db1, name = "B", grade = 1)
println(s"db2: $db2")

val db3 = add(db2, name = "C", grade = 2)
println(s"db3: $db3")

Works fine for me. Only thing I'd mention is that add expects Int, String , where you're calling it as add(2, "Mike") (ie Int, String ) - this won't compile. Here's the output of my Scala console (after flipping the order of the input variables when calling your add method):

scala> type DB = Map[Int, Seq[String]]
defined type alias DB

scala> var grades: DB = Map.empty
grades: DB = Map()

scala> def add(name: String, grade: Int) = {
     |   var names: Seq[String] = Seq(name)
     |   if(grades isDefinedAt grade) {
     |     names = names ++ grades(grade)
     |   }
     |   grades += (grade -> names)
     | }
add: (grade: Int, name: String)Unit

scala> 

scala> add("Mike", 2)

scala> add("Michelle", 2)

scala> add("John", 2)

scala> grades
res3: DB = Map(2 -> List(John, Michelle, Mike))

I'm not sure why it didn't work for you. If you had got the first two inputs the wrong way around like I initially thought, ie add(2, "Mike") etc, you would expect the output to be (2, List(John)) and not just (2, John) . I think you broke the laws of Scala there.

Just as a "best practice" thing, it would be better to avoid var where possible. This could be rewritten without mutable variables. There's a good article by alvinalexander which explains the preference for immutable variables. Worth a read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM