0

可以说有一堂课

case class User(id: Long, firstName: String, surName: String, password: String)

和一张地图

var userMap = Map(
    1 -> User(1, "firstName1", "surName1", "1111"),
    2 -> User(2, "firstName2", "surName2", "2222"),
    3 -> User(3, "firstName3", "surName3", "3333")
)

通过这样做

userMap find { case (a,b) => b == (1, "firstName1", "surName1", "1111") } isDefined

我可以找到是否存在该值,但是

例如,我如何找到 userMap 中是否有 surName1,如果需要更改它,如果没有这样的姓氏,则返回 true 或 false?

谢谢你。

4

3 回答 3

2

除了匹配值的所有属性之外,几乎您现在拥有的只是在属性上显式匹配surName

userMap.find{case (i, user) => user.surName == "surName1"}.isDefined
res0: Boolean = true

scala> userMap.find{case (i, user) => user.surName == "foo"}.isDefined
res1: Boolean = false
于 2013-09-26T16:40:11.187 回答
1

而不是使用 find ... isDefined 如果您只想检查所述项目的存在,您最好选择存在:

userMap exists { 
   case (_, user) => user == User(1, "firstName1", "surName1", "1111") 
}

接下来,如果你想

例如,我如何查找 userMap 中是否有 surName1,如果有更改它,如果没有这样的姓氏,则返回 true 或 false

你的代码没有太多改变:

val found = userMap find { case (k,user) => user == User(_, _, "surName1", _) } 
// or with field access as @brian showed
found.foreach { case (key, value) => // do update with userMap by found key } 
found.isDefined 
于 2013-09-26T16:42:36.367 回答
0
scala>  userMap.values.exists{ case User(_, surName1, _, _ ) => true }
res1: Boolean = true

但是,如果您要进行更改,请不要检查是否为真,然后去做。这是必要的非 scala 思维方式。这是一种温和的邪恶方式:

var changed = false
userMap map { x => x match {
    case (n, User(i, f, "surName1", p)) => {
      changed = true
      (n, User(i, f, "Appleyard", p))
    }
    case _ => x
  }
}

这样做是返回 userMap 的副本(因为您的 userMap 可能是不可变的,除非您指定了可变映射),任何“surName1”用户都更改为“Appleyards”。如果找到任何匹配的用户,“已更改”将设置为 true 作为副作用。我称之为轻度邪恶,因为它使用副作用。请注意,有一种非常简单的方法可以避免副作用...

scala> newMap = userMap  map { x => x match {
    case (n, User(i, f, "surName1", p)) => {
      (n, User(i, f, "Appleyard", p))
    }
    case _ => x
  }
}

scala> newMap == userMap
res2: Boolean = false

现在这里有更正式的东西

def surnameA2B(oldName: String, newName: String, m: Map[Int,User]): (Int, Map[Int,User]) = {
  val changed = m collect {
    case (n, User(i, f, s, p)) if s == oldName =>
      (n, User(i, f, newName, p))
  }
  (changed.size, m ++ changed)
}

surnameA2B("surName1", "Appleyard", userMap)
res1: (Int, Map[Int,User]) = (1,Map(1 -> User(1,firstName1,Appleyard,1111), 2 -> User(2,firstName2,surName2,2222), 3 -> User(3,firstName3,surName3,3333)))

给定要匹配的名称、替换名称和用户映射,它会返回已更改用户的计数和已更改的新用户映射。0 表示没有变化,因此您可以通过测试计数是否为 0 来得出布尔值。

检查一个条件,如果它是真的就采取行动,然后根据动作设置一个条件是一种非常必要的、非 Scala 的做事方式。事实上,很少需要检查一个条件是否为真,当您可以链接函数时,如果 B 完成,A 将自然发生(如果需要,对于 B 的每个相关迭代。Scala 使尝试这种方法变得容易,并且它会产生更清晰的代码。

于 2013-09-26T18:47:59.123 回答