Scala 如何处理地图中有价值的对象?

Scala 如何处理地图中有价值的对象?,scala,scala-collections,scala-2.10,Scala,Scala Collections,Scala 2.10,假设有一节课 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, "first

假设有一节课

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中是否有姓氏1,如果有,如何更改它,如果没有这样的姓氏,如何返回true或false


谢谢。

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

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

除了在值的所有属性上进行匹配之外,您现在拥有的几乎都是在
姓氏
属性上显式匹配的

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

而不是使用查找。。。isDefined如果您只想检查所述项目是否存在,您最好选择“存在”:

userMap exists { 
   case (_, user) => user == User(1, "firstName1", "surName1", "1111") 
}
下一步,如果你想

例如,我如何才能找到userMap中是否有姓氏1,如果有,如何更改它,如果没有这样的姓氏,如何返回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 

而不是使用查找。。。isDefined如果您只想检查所述项目是否存在,您最好选择“存在”:

userMap exists { 
   case (_, user) => user == User(1, "firstName1", "surName1", "1111") 
}
下一步,如果你想

例如,我如何才能找到userMap中是否有姓氏1,如果有,如何更改它,如果没有这样的姓氏,如何返回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 
但是如果你要改变,不要检查是否正确,然后去做。这是一种非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可能是不可变的),任何“姓氏1”的用户都更改为“Appleyards”。如果找到任何匹配的用户,“changed”将作为副作用设置为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)))
给定要匹配的名称、替换名称和usermap,它将返回已更改用户的计数和已发生更改的新usermap。0表示没有更改,因此您可以通过测试计数是否为0来派生布尔值

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

但是,如果你要做出改变,不要检查是否正确,那么就去做。这是非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可能是不可变的),任何“姓氏1”用户都将更改为“Appleyards”。如果找到任何匹配的用户,则“更改”将被设置为真作为副作用。我称之为轻度邪恶,因为它使用副作用。请注意,有一个非常简单的方法可以避免副作用

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)))
给定要匹配的名称、替换名称和usermap,它将返回已更改用户的计数和已进行更改的新usermap。0表示没有更改,因此您可以通过测试计数是否为0来派生布尔值


检查一个条件,如果它是真的,那么就采取行动,然后根据行动设置一个条件,这是一种非常必要的、非Scala的方式。事实上,很少需要检查一个条件是否是真的,因为你可以链接函数,这样,如果B完成,a就会自然发生(如有必要,对于B的每个相关迭代,Scala可以很容易地尝试这种方法,并产生更干净的代码。

您的意思是
B==User(1,“firstName1”,“姓氏1”,“1111”)
?你可能需要一个镜头:看第二个答案。@WeaponsGrade可能比OP更先进,但肯定是任何人都应该感兴趣的东西。你是说
b==User(1,“firstName1”,“姓氏1”,“1111”)
?你可能需要一个镜头:看第二个答案。@WeaponsGrade可能比OP更先进,但肯定是任何人都应该感兴趣的东西。为什么第一个不是userMap.values.exists?@itsbruce是的,它可能是
userMap.values.exists
以及为什么第一个不是userMap.values.exists?@itsbruce是的,它也可以是
userMap.values.exists