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

时间:2013-09-26 16:30:45

标签: 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, "firstName3", "surName3", "3333")
)

通过这样做

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

我可以找到是否有该值,但是

如何在userMap中查找是否存在surName1,如果要更改它并返回true或false,如果没有这样的姓氏?

谢谢。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 

答案 2 :(得分: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可以很容易地尝试这种方法和它会产生更清晰的代码。