【问题标题】:How to handle objects that are value in map?如何处理地图中有价值的对象?
【发布时间】:2013-10-02 17:54:01
【问题描述】:

假设有一个类

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?

谢谢。

【问题讨论】:

  • 你的意思是b == User(1, "firstName1", "surName1", "1111")
  • 你可能想要一个镜头:看第二个答案here
  • @WeaponsGrade 可能比 OP 更先进,但绝对是任何人都应该感兴趣的东西。

标签: scala scala-collections scala-2.10


【解决方案1】:

除了匹配值的所有属性之外,几乎您现在拥有的只是在 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

【讨论】:

    【解决方案2】:

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

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

    接下来,如果你想

    我怎样才能找到,例如,userMap 中是否有 surName1,如果有更改它,如果没有这样的 surname,则返回 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 
    

    【讨论】:

    • 为什么 userMap.values.exists 不是第一个?
    • @itsbruce 是的,也可以是 userMap.values.exists
    【解决方案3】:
    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 使尝试这种方法变得容易,并且它会产生更清晰的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-05
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多