0

Lets say there is a class

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

and a map

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

by doing that

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

I can find if there is that value or not, but

how can I find if there is, for instance, surName1 in the userMap, if there is to change it and return me true or false if there is no such a surname?

Thank you.

jimakos17
  • 905
  • 4
  • 14
  • 33
  • Do you mean `b == User(1, "firstName1", "surName1", "1111")`? – om-nom-nom Sep 26 '13 at 16:40
  • You may want a lens: look at the second answer [here](http://stackoverflow.com/questions/3900307/cleaner-way-to-update-nested-structures). – WeaponsGrade Sep 26 '13 at 19:54
  • @WeaponsGrade Possibly more advanced than the OP is quite ready for, but definitely something anybody should be interested in. – itsbruce Sep 27 '13 at 12:41

3 Answers3

2

Almost what you have now except for matching on all properties of the value just explicitly match on the surName property.

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
Brian
  • 20,195
  • 6
  • 34
  • 55
1

Instead of using find ... isDefined you would be better to opt to exists if you want to just check existence of said item:

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

Next, if you want to

how can I find if there is, for instance, surName1 in the userMap, if there is to change it and return me true or false if there is no such a surname

There is not much to change to you code:

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 
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
0
scala>  userMap.values.exists{ case User(_, surName1, _, _ ) => true }
res1: Boolean = true

But if you're going to make a change, don't check for true then do it. That's imperative non-scala way of thinking. Here's a mildly evil way of doing that:

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
  }
}

What this does is return a copy of userMap (because your userMap is probably immutable unless you specified a mutable map), with any "surName1" users changed to "Appleyards". If any matching users were found, "changed" will be set to true as a side-effect. I call this mildly evil because it uses side effects. Mind you, there's a very simple way of avoiding the side-effect...

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

Now here's something more formal

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)))

Given a name to match, a replacement name and a usermap, it returns a count of the changed users and a new usermap with the changes in place. 0 means no changes, so you can derive your boolean just by testing if the count is 0 or not.

Checking for a condition, then acting if it is true, then setting a condition based on the actions is a very imperative, non-Scala way of doing things. In fact, it is rarely necessary to check if a condition is true, when you can chain functions so that A will naturally happen if B completed (and for each relevant iteration of B, if necessary. Scala makes it easy to try this approach and it results in cleaner code.

itsbruce
  • 4,825
  • 26
  • 35