This:
val checkValue = udf { (array: WrappedArray[String], value: String) => array.contains(value) }
works if you do not worry about case of words.
I can apply .toLowerCase() to value easily enough to get this ...(value.toLowerCase() )
But how to apply to the incoming array being WrappedArray and not externally?
array.contains(value)
is the same as
array.exists(_ == value)
The _ == value can be replaced by an arbitrary predicate.
In your case, it would be something like
array.exists(value.equalsIgnoreCase)
Also, note that "ß".toUpperCase == "SS" is true, whereas "ß" == "SS".toLowerCase and "ß".compareIgnoreCase("SS") are both false, see for example this answer.
Related
I have a Future[List[Result]]
I need to run a logic for example if all items in the list are Result.Ok then return Result.Ok (or true), else return Result.BadRequest (or false)
I've tried:
futureResultList.map(temp => temp.forall(_ == true))
But this code works only when the list contains booleans. It does not work if it contains Result objects (When changing check to _ == Result.Ok)
To return a Boolean you just need to change the predicate in the forall call:
futureResultList.map(_.forall(_ == Result.Ok))
The simplest way to overview such an example is mapping. If you have a List of Result, but need a List of Boolean, then map it. Don't be afraid of mapping multiple times, it's way more readable in the long run :)
val futureResultList: Future[List[Result]] = ???
val futureBooleanList: Future[List[Boolean]] = futureResultList.map(_.map(_ == Result.OK))
val result = futureBooleanList.map(temp => temp.forall(_ == true))
or slightly more concise:
val futureResultList: Future[List[Result]] = ???
val result = futureResultList.map(_.map(_ == Result.OK)
.forall(_ == true))
and of course as the other people suggest, go directly to checking the equality on the Result object. But mapping is often useful to navigate between types and getting a clearer and more readable code.
I have two vals, a condition and an option. Note that condition is a simple boolean, not depending on the option's value.
If condition holds true, I would like to map over the option to convert it to a result value. In all other cases, I would like to return a defaultResult.
This works and is quite readable, but I dislike the duplication of defaultResult:
val result = if (condition) {
option.map(valueToResult).getOrElse(defaultResult)
} else {
defaultResult
}
My second approach does not have duplications, but I dislike the fact that filter is abused for something that is not actually dependent on the option's value:
val result = option.filter(_ => condition).map(valueToResult).getOrElse(defaultResult)
What's a more idiomatic or otherwise better approach in Scala?
You can use Option.collect:
Returns a scala.Some containing the result of applying pf to this
scala.Option's contained value, if this option is nonempty and pf is
defined for that value.
val result = option.collect {
case x if condition => valueToResult(x)
}.getOrElse(defaultResult)
val result = option match {
case Some(value) if condition => valueToResult(value)
case _ => defaultResult
}
val result = (for (v<-option if condition) yield valueToResult(v)).getOrElse(defaultResult)
option.foldLeft(defaultResult)((d,x) => if (condition) valueToResult(x) else d)
val result = (condition match {
case true => option.map(valueToResult)
case false => None
}).getOrElse(defaultResult)
I need return tuple , but if something goes wrong I want return empty tuple, like Seq.empty[Type] or Nil in Lists. Is it possible?
Also I am curious about is it possible with String type.
I want return empty tuple
That doesn't make sense. A tuple is not a collection. The idea of "emptiness" is simply non-sensical. The length of a tuple is part of its type. So, an empty tuple is a different type than a non-empty tuple.
In fact, it doesn't even make sense to talk about "tuple" as a type. There are pairs (2-tuples aka Tuple2), triples (3-tuples aka Tuple3), quadruples, quintuples, sixtuples, septuples, octuples, 9-tuples, 10-tuples, etc, and they are all different types.
Also, more or less the only sensible thing you can do with a tuple is to extract its elements. So, for a tuple with no elements, there is pretty much no sensible thing you can do. What use is a structure that holds no values and has no operations? It's completely useless.
In fact, a 0-tuple is isomorphic to the Unit value, the value which denotes the absence of a useful value. In Scala, and also Haskell, the syntax for an empty tuple is actually used for denoting the Unit value:
val u = ()
// => u: Unit = ()
Also I am curious about is it possible with String type.
Yes, of course, you can have an empty string:
val s = ""
// => s: String = ""
Since you need to return an a value that can go wrong. In Scala the recommended way to deal with this is returning an Option, Try or Either value.
For instance:
def somethingThatCanGoWrongWithTry(): Try[(Int, String)] = {
Try{
val intValue = sideEffectValueInt()
val stringValue = sideEffectValueString()
(intValue, stringValue)
}
}
def somethingThatCanGoWrongWithOption(): Option[(Int,String)] = {
Try {
val intValue = sideEffectValueInt()
val stringValue = sideEffectValueString()
(intValue, stringValue)
}.toOption
}
def somethingThatCanGoWrongWithEither(): Either[Oops, (Int,String)] = {
Try {
val intValue = sideEffectValueInt()
val stringValue = sideEffectValueString()
(intValue, stringValue)
} match {
case Success(value) => Right(value)
case Failure(exception) => Left(Oops(exception))
}
}
Is there any better way to do following?
val v = map.get(key)
v match {
case None => default
case Some(str) => {
if(str == null) default else str << how to avoid additional null check here
}
}
Option.apply works intelligently with null:
val myNullString: String = null
Option(myNullString) //None
So one option would be:
map.get(key).flatMap(Option.apply).getOrElse(default)
You could also filter all the null values from the map first. You might also be interested in the getOrElse or withDefaultValue methods on Map for these types of operations:
map.filter(_._2 != null).getOrElse(key, default)
map.filterNot(_._2 == null).withDefaultValue(default)(key)
You could also use collectFirst here (this is more general, since you can apply it to arbitrary key-value tuples, but you lose the efficiency of constant lookup):
map collectFirst { case (`key`, str) if str != null => str } getOrElse default
I'm splitting an input of type Option[String] into an Option[Array[String]] as follows:
val input:Option[String] = Option("a=b,1000,what?")
val result: Option[Array[String]] = input map { _.split(",") }
I want to add a test whereby if any member of the array matches (eg, is an Long less than 0), the whole array is discarded and an empty Option returned.
Use filter to perform a test on the content of an Option.
Use exists to check whether any member of the collection fullfils a condition.
result.filter(! _.exists(s => test(s)))
or
result.filterNot(_.exists(s => test(s)))
Have you considered using find() on the collection ? If it returns a Some(x), then something has satisfied the condition.
list.find(_ < 0) match {
case Some(x) => None
case None => Some(list)
}
Of course you know that you can split and then filter as #ziggystar suggests, but if you have a really big Stringand an element at the beginning matches then it's pointless to finish splitting the string when you know it's going to be discarded.
In this case, if you're worried about time efficiency, you can use a Stream and re-implement the split operation, something like this:
def result(input:Option[String]):Option[Seq[String]] = {
def split(c: Char, chars:Stream[Char]):Stream[String] = {
val (head,tail) = chars span(_ != c)
head.mkString #:: (if(tail isEmpty) Stream.empty else split(c, tail tail))
}
input map {s => split(',', Stream(s:_*)) } filter (_.forall (s => !test(s)))
}
Note that the map/filter structure stays the same, but it is now short-circuiting due to the use of Stream.
If it's a really big string you probably have it as a Stream[Char] already which means you don't even have the memory overhead of hanging on the original String.