Pattern Matching Pass Through in Scala - scala

I want to do something like this:
val a = v match {
case 1 => 1
case 2 if (condition) => logging
case 2 if (other conditions) => 3
case 2 if (more conditions) => 4
case _ => 5
}
I want this to return just log for first case 2, but fall through otherwise to see what gets returned
edit: updated

Scala's case matching doesn't "fall through", but if I understand correctly, this will do what you want.
val a = v match {
case 1 => 1
case 2 => {
logging // I'm assuming `logging` is some Unit
if(some condition) 3
else if(some other condition) 4
else 5
}
case _ => 5
}

Something like this?
If v == 2, a will be assigned logging otherwise a will be assigned the value of v
val a = v match {
case 2 => logging
case _ => v
}

Related

Modifying the list while using for comprehension in Scala

I have a list that contains all possible deals between clients, and every sell-buy combination needs to be compared. With the comparison, another list need to be modified.
I have the following code:
def res(input_orders: List[Order], input_clients: List[Client]): List[Client] = {
for {
order1 <- input_orders
order2 <- input_orders if check_order(order1, order2)
firstClient = input_clients.find(_.name == order1.client)
secondClient = input_clients.find(_.name == order2.client)
tmp <- if (order1.operation == 's') {
input_clients.map { case `firstClient` => sell(firstClient.get, order1); case x => x }
input_clients.map { case `secondClient` => buy(secondClient.get, order2); case x => x }
} else {
input_clients.map { case `firstClient` => buy(firstClient.get, order1); case x => x }
input_clients.map { case `secondClient` => sell(secondClient.get, order2); case x => x }
}
} yield tmp
}
But it returns the list of clients as it is and does not modify it.
I suppose that the problem is in this "modification" block:
input_clients.map { case `firstClient` => sell(firstClient.get, order1); case x => x }
input_clients.map { case `secondClient` => buy(secondClient.get, order2); case x => x }
} else {
input_clients.map { case `firstClient` => buy(firstClient.get, order1); case x => x }
input_clients.map { case `secondClient` => sell(secondClient.get, order2); case x => x }
What is wrong with it?
Recall that the map function is immutable which means it doesn't do any modification to the datastructure but rather returns a new object which content has been updated.
In the block you're mentioning, the first calls of mapare useless because the return value is never used. A proper way of achieving the task you initially wanted to do would be:
val order = order1.operation == 's'
input_clients.map {
case `firstClient` => if (order) sell(firstClient.get, order1) else buy(firstClient.get, order1)
case `secondClient` => if (order) buy(secondClient.get, order2) else sell(secondClient.get, order2)
case x => x
}
Moreover, avoid using the get accessor of an Option[T] (imagine what would happen if the option was None). Prefer safer operations like pattern matching or flatMap / for-comprehension instead.

Pattern Matching Case Match using Scala

Having issues with trying to get my case match to work as expected.
The outcome I am looking for is as follows:
case 1 OR 2 => randomly select one reference
case any other number above 2 => randomly select (number - 2) reference
case None => throw exception
Im having problems implementing this. so far I have:
val randomList: List = actualList.size match {
case 1 => scala.util.Random.shuffle(actualList).take(1)
case x? => scala.util.Random.shuffle(actualList).take(2)
case None => throw new IllegalStateException("references have not been generated successfully.")
}
I get an error message with the 'None' stating the pattern type is incompatible with expected type Int.
If there is a better way to implement this, please do share.
Any help would be much appreciated.
Thanks
I think you can shuffle right away to simplify each expression in case clauses:
val actualList = List(1, 2, 3)
val shuffled = Random.shuffle(actualList)
shuffled.size match {
case 0 => throw new RuntimeException()
case 1 | 2 => shuffled.take(1)
case _ => shuffled.take(2)
}
You can use |, guard and _ to achieve this
val randomList: List = actualList.size match {
case 0 => throw new IllegalStateException("references have not been generated successfully.")
case 1 | 2 => scala.util.Random.shuffle(actualList).take(1)
case _ => scala.util.Random.shuffle(actualList).take(2)
}

condition matching in an array with case class in scala

I have a task need to find a particular string in an array:
1. if found, return its value;
2. if not found, return -1.
I wrote an "idea" code, but I don't know how to finish it correctly.
case class person(name:String, value: Int)
personList[Array[person]]
val result = personList match {
case x if x.name == "john" => x.value
case _ => -1 }
the complier reports errors at "case x if x.name"
Would this work for you?
persons.find(_.name == "john").fold(-1)(_.value)
Note: I've left the creation and/or population of the persons array up to you.
val result = personList.find(_.name=="john") match {
case some(x) => x.value
case None => -1 }

Multiple conditions in the same guarded case statement in Scala?

I have several conditions that I want to stack in a scala match statement. In another language I could just omit the 'break' between the cases of a switch statement.
I know I can combine raw alternatives separated by a pipe character, but can't seem to find how to combine guarded cases, e.g.:
val isAdmin = true
myval match {
case 1 if isAdmin => ...
case 2 if isAdmin => ...
case 1 | 2 => // this is fine but doesn't apply the guard, so no use
case 1 | 2 if isAdmin => // doesn't apply the guard to '1'
case 1 if isAdmin | 2 if isAdmin => // invalid syntax
}
Is it possible to combine the first two cases somehow?
The guard statement applies to everything, for good or for ill. This means that your example
case 1 | 2 if isAdmin => ...
actually does what you want and what you say it does not, but it also means that
Option("Hi") match {
case Some(x) | None if x == "Hi" => 1
case _ => 0
}
does not work. (In fact, it doesn't even compile.)
Fortunately, Scala lets you drop a def in practically anywhere.
def caseNice = 1
Option("Hi") match {
case Some(x) if x.length < 3 => caseNice
case None => caseNice
case _ => 0
}
which is how you should deal with common functionality that is difficult invoke from a single case statement.

Scala large listing of cases in pattern matching

For a long listing of cases which return a value within a limited domain, how to reduce the otherwise growing number of case declarations ? For instance consider
"abc" match {
case "a" => 1
case "ab" => 1
case "aw" => 2
case "hs" => 2
case "abc" => 1
case _ => 0
}
Tried a Map[Set[String],Int] where
val matches = Map( Set("a","ab","abc") -> 1, Set("aw","hs") -> 2 )
and defined
def getMatch(key: String, m: Map[Set[String],Int]) = {
val res = m.keys.collectFirst{ case s if s(key) => m(s) }
res.getOrElse(0)
}
Are there simpler and/or more efficient approaches to this ?
You can group your cases:
"abc" match {
case "a" | "ab" | "abc" => 1
case "aw" | "hs" => 2
case _ => 0
}
You can create your own matchers like this:
class InSet[T](set: Set[T]) {
def unapply(t: T) = set.find(t)
}
val set1 = new InSet(Set("a","ab","abc"))
val set2 = new InSet(Set("aw","hs"))
"aw" match {
case set1(a) => "1, " + a
case set2(a) => "2, " + a
case _ => "3"
}
The good thing about this is that it makes it easy to create and apply very different matchers.
You can shift the complexity a bit by doing this:
val m = matches.flatMap { case (xs,i) => xs.map(_ -> i) }.withDefaultValue(0)
m("abc") // 1
m("z") // 0
Thus avoiding the need to call things through your getMatch function. Possibly faster too since you upfront the work instead of iterating through the keys every time you need call getMatch.