Getting the element from a 1-element Scala collection - scala

Learning Scala and I keep wanting an equivalent to LINQ's Single() method. Example,
val collection: Seq[SomeType]
val (desiredItem, theOthers) = collection.partition(MyFunc)
desiredItem.single.doSomething
// ^^^^^^
I could use desiredItem.head but what if MyFunc actually matched several? I want the assurance that there's only one.
Edit #2 The duplicate question says 'no there isn't but here's how to build it'. So I am thinking if this was a common need it would be in the base API. Do properly written Scala programs need this?

I'd use something more verbose instead of single:
(desiredItem match {
case Seq(single) => single
case _ => throw IllegalStateException("Not a single element!")
}).doSomething
Its advantage over single is that it allows you to explicitly control the behavior in exceptional case (trow an exception, return fallback value).
Alternatively you can use destructuring assignment:
val Seq(single) = desiredItem
single.doSomething
In this case you'll get MatchError if desiredItem doesn't contain exactly one element.
UPD: I looked again at your code. Destructuring assignment is the way to go for you:
val collection: Seq[SomeType]
val (Seq(desiredItem), theOthers) = collection.partition(MyFunc)
desiredItem.doSomething

There's no prebuilt method in the API to do that. You can create your own method to do something similar though.
scala> def single[A](xs: List[A]) = xs match{
| case List() => None
| case x::Nil => Some(x)
| case x::xs => throw new Exception("More than one element")
| }
single: [A](xs: Seq[A])Option[A]
scala> single(List(1,2,3))
java.lang.Exception: More than one element
at .single(<console>:11)
... 33 elided
scala> single(List(1))
res13: Any = Some(1)
scala> single(List())
res14: Any = None

Like others indicated, there is no library implementation of what you seek. But it's easy to implement your own using a Pimp My Library approach. For example you can do the following.
object Main extends App {
object PML {
implicit class TraversableOps[T](val collection: TraversableOnce[T]) {
def single: Option[T] = collection.toList match {
case List(x) => Some(x)
case _ => None
}
}
}
import PML._
val collection: Seq[Int] = Seq(1, 2)
val (desiredItem, theOthers) = collection.partition(_ < 2)
println(desiredItem.single) // Some(1)
println(collection.single) // None
println(List.empty.single) // None
}

Related

Convert Seq[Try[Option(String, Any)]] into Try[Option[Map[String, Any]]]

How to conveniently convert Seq[Try[Option[String, Any]]] into Try[Option[Map[String, Any]]].
If any Try before convert throws an exception, the converted Try should throw as well.
Assuming that the input type has a tuple inside the Option then this should give you the result you want:
val in: Seq[Try[Option[(String, Any)]]] = ???
val out: Try[Option[Map[String,Any]]] = Try(Some(in.flatMap(_.get).toMap))
If any of the Trys is Failure then the outer Try will catch the exception raised by the get and return Failure
The Some is there to give the correct return type
The get extracts the Option from the Try (or raises an exception)
Using flatMap rather than map removes the Option wrapper, keeping all Some values and discaring None values, giving Seq[(String, Any)]
The toMap call converts the Seq to a Map
Here is something that's not very clean but may help get you started. It assumes Option[(String,Any)], returns the first Failure if there are any in the input Seq and just drops None elements.
foo.scala
package foo
import scala.util.{Try,Success,Failure}
object foo {
val x0 = Seq[Try[Option[(String, Any)]]]()
val x1 = Seq[Try[Option[(String, Any)]]](Success(Some(("A",1))), Success(None))
val x2 = Seq[Try[Option[(String, Any)]]](Success(Some(("A",1))), Success(Some(("B","two"))))
val x3 = Seq[Try[Option[(String, Any)]]](Success(Some(("A",1))), Success(Some(("B","two"))), Failure(new Exception("bad")))
def f(x: Seq[Try[Option[(String, Any)]]]) =
x.find( _.isFailure ).getOrElse( Success(Some(x.map( _.get ).filterNot( _.isEmpty ).map( _.get ).toMap)) )
}
Example session
bash-3.2$ scalac foo.scala
bash-3.2$ scala -classpath .
Welcome to Scala 2.13.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66).
Type in expressions for evaluation. Or try :help.
scala> import foo.foo._
import foo.foo._
scala> f(x0)
res0: scala.util.Try[Option[Equals]] = Success(Some(Map()))
scala> f(x1)
res1: scala.util.Try[Option[Equals]] = Success(Some(Map(A -> 1)))
scala> f(x2)
res2: scala.util.Try[Option[Equals]] = Success(Some(Map(A -> 1, B -> two)))
scala> f(x3)
res3: scala.util.Try[Option[Equals]] = Failure(java.lang.Exception: bad)
scala> :quit
If you're willing to use a functional support library like Cats then there are two tricks that can help this along:
Many things like List and Try are traversable, which means that (if Cats's implicits are in scope) they have a sequence method that can swap two types, for example converting List[Try[T]] to Try[List[T]] (failing if any of the items in the list are failure).
Almost all of the container types support a map method that can operate on the contents of a container, so if you have a function from A to B then map can convert a Try[A] to a Try[B]. (In Cats language they are functors but the container-like types in the standard library generally have map already.)
Cats doesn't directly support Seq, so this answer is mostly in terms of List instead.
Given that type signature, you can iteratively sequence the item you have to in effect push the list type down one level in the type chain, then map over that container to work on its contents. That can look like:
import cats.implicits._
import scala.util._
def convert(listTryOptionPair: List[Try[Option[(String, Any)]]]): Try[
Option[Map[String, Any]]
] = {
val tryListOptionPair = listTryOptionPair.sequence
tryListOptionPair.map { listOptionPair =>
val optionListPair = listOptionPair.sequence
optionListPair.map { listPair =>
Map.from(listPair)
}
}
}
https://scastie.scala-lang.org/xbQ8ZbkoRSCXGDJX0PgJAQ has a slightly more complete example.
One way to approach this is by using a foldLeft:
// Let's say this is the object you're trying to convert
val seq: Seq[Try[Option[(String, Any)]]] = ???
seq.foldLeft(Try(Option(Map.empty[String, Any]))) {
case (acc, e) =>
for {
accOption <- acc
elemOption <- e
} yield elemOption match {
case Some(value) => accOption.map(_ + value)
case None => accOption
}
}
You start off with en empty Map. You then use a for comprehension to go through the current map and element and finally you add a new tuple in the map if present.
The following solutions is based on this answer to the point that almost makes the question a duplicate.
Method 1: Using recursion
def trySeqToMap1[X,Y](trySeq : Seq[Try[Option[(X, Y)]]]) : Try[Option[Map[X,Y]]] = {
def helper(it : Iterator[Try[Option[(X,Y)]]], m : Map[X,Y] = Map()) : Try[Option[Map[X,Y]]] = {
if(it.hasNext) {
val x = it.next()
if(x.isFailure)
Failure(x.failed.get)
else if(x.get.isDefined)
helper(it, m + (x.get.get._1-> x.get.get._2))
else
helper(it, m)
} else Success(Some(m))
}
helper(trySeq.iterator)
}
Method 2: directly pattern matching in case you are able to get a stream or a List instead:
def trySeqToMap2[X,Y](trySeq : LazyList[Try[Option[(X, Y)]]], m : Map[X,Y]= Map.empty[X,Y]) : Try[Option[Map[X,Y]]] =
trySeq match {
case Success(Some(h)) #:: tail => trySeqToMap2(tail, m + (h._1 -> h._2))
case Success(None) #:: tail => tail => trySeqToMap2(tail, m)
case Failure(f) #:: _ => Failure(f)
case _ => Success(Some(m))
}
note: this answer was previously using different method signatures. It has been updated to conform to the signature given in the question.

Avoiding nested Ifs when working with multiple Options and Eithers

When I am coding with options I find the fold method very useful. Instead of writing if defined statements I can do
opt.fold(<not_defined>){ defined => }
this is good. but what to do if we are working with multiple options. or multiple eithers. Now I have to resort to writing code like
if (x.isDefined && y.isRight) {
val z = getSomething(x.get)
if (z.isDefined) {
....
Depending on the number of things involved, this code becomes very nested.
is there a functional trick to make this code a little un-nested and concise.... like the fold operation above?
have you tried for comprehension? Assuming you don't want to treat individual errors or empty optionals:
import scala.util._
val opt1 = Some("opt1")
val either2: Either[Error, String] = Right("either2")
val try3: Try[String] = Success("try3")
for {
v1 <- opt1
v2 <- either2.right.toOption
v3 <- try3.toOption
} yield {
println(s"$v1 $v2 $v3")
}
Note that Either is not right biased, so you need to call the .right method on the for comprehension (I think cats or scalaz have a right biased Either). Also, we are converting the Either and the Try to optionals, discarding errors
Cases when .isDefined is followed by .get call can be refactored using custom extractors for pattern matching:
def getSomething(s: String): Option[String] = if (s.isEmpty) None else Some(s.toUpperCase)
object MyExtractor {
def unapply(t: (Option[String], Either[Int, String])): Option[String] =
t match {
case (Some(x), Right(y)) => getSomething(x)
case _ => None
}
}
val x: Option[String] = Some("hello world")
val y: Either[Int, String] = Right("ok")
(x, y) match {
case MyExtractor(z) => z // let's do something with z
case _ => "world"
}
// HELLO WORLD
We managed to get rid of all .isDefined, .get and even .right calls by replacing them by explicit pattern matching thanks to our custom extractor MyExtractor.

Concise way in Scala to combine filterNot/match/case

I need to filter a sequence to remove an element that matches a certain case.
This seems too clumsy:
val filtered =
headers.filterNot{ case Authorization(_) => true; case _ => false }
Is there a more concise/idiomatic way?
You can use isInstanceOf, like this
headers.filterNot(_.isInstanceOf[Authorization])
You can use PartialFunction.cond to omit the false case:
import PartialFunction.cond
headers.filterNot(cond(_) { case Authorization(_) => true } )
Your way of doing things seems fine. Alternatively, you could take advantage of the fact that case statements are PartialFunctions and leverage that. Unfortunately, Scala's finicky type inference makes this more verbose than it should (otherwise it would be quite a nice little idiom).
// Ideal, but Scala's type inference lets us down and this won't compile :(
val filtered0 = headers.filterNot({ case Authorization(_) =>}.isDefinedAt)
// This will compile, but is crazily verbose
val filtered1 = headers.filterNot(({ case Authorization(_) =>}: PartialFunction[spray.http.HttpHeader, Option[Unit]]).isDefinedAt)
Or you can wrap this all up in an implicit class and take care of the type signature there and leave the call-site pristine.
implicit class Matches[T](x: T){
def matches(pf: PartialFunction[T, Any]) = pf isDefinedAt x
}
val filtered2 = headers filterNot (_ matches {case Authorization(_) =>})
List(Some(1), None) filterNot (_ matches {case None =>}) // List(Some(1))
Because this is just taking advantage of the fact that case statements are PartialFunctions, this works for arbitrary patterns.
List((5, 2, 'a'), (3, 4, 'b'), (3, 2, 'c')) filterNot (_ matches {case (3, _, x) if x == 'c' =>})
// List((5, 2, a), (3, 4, 'b'))
The matches idea is a minor cosmetic reworking of Adriaan Moors' idea on the Scala mailing list debating whether to add matches as its own syntactic feature where the OP runs into the exact problem you describe.
Similar to the original proposal, yet pattern matching on types,
headers.filter {
case x: Authorization => false
case _ => true
}
Another approach involves the definition of a filtering predicate,
def noAuth(h: Header): Boolean = h match {
case h: Authorization => false
case _ => true
}
used then for filtering,
headers.filter(noAuth)
scala> sealed trait Header
defined trait Header
scala> case object Token extends Header
defined object Token
scala> case class Authorization(x: String) extends Header
defined class Authorization
scala> val headers: List[Header] = List(Token, Authorization("foo"))
headers: List[Header] = List(Token, Authorization(foo))
You could use flatMap even though it doesn't buy you anything other than filterNot. Although I, personally, find flatMap easier to understand than filterNot - mainly due to my habit of using filter, but not filterNot:
scala> headers.flatMap {
| case Authorization(_) => Nil
| case other => List(other)
| }
res1: List[Header] = List(Token)

Scala extractors: a cumbersome example

Everything started from a couple of considerations:
Extractors are Scala objects that implements some unapply methods with certain peculiarities (directly from «Programming in Scala 2nd edition», I've checked)
Objects are singletons lazy initialised on the static scope
I've tried to implement a sort of «parametric extractors» under the form of case classes to try to have an elegant pattern for SHA1 checking.
I'd like to check a list of SHA1s against a buffer to match which of them apply. I'd like to write something like this:
val sha1: Array[Byte] = ...
val sha2: Array[Byte] = ...
buffer match {
case SHA1(sha1) => ...
case SHA1(sha2) => ...
...
}
Ok, it looks weird, but don't bother now.
I've tried to solve the problem by simply implementing a case class like this
case class SHA1(sha1: Array[Byte]) {
def unapply(buffer: Array[Byte]): Boolean = ...
}
and use it like
case SHA1(sha1)() =>
and even
case (SHA1(sha1)) =>
but it doesn't work: compiler fails.
Then I've a little changed the code in:
val sha1 = SHA1(sha1)
val sha2 = SHA1(sha2)
buffer match {
case sha1() => println("sha1 Match")
case sha2() => println("sha2 Match")
...
}
and it works without any issue.
Questions are:
Q1: There are any subtle implications in using such a kind of «extractors»
Q2: Provided the last example works, which syntax was I supposed to use to avoid to define temporary vals? (if any provided compiler's job with match…case expressions)
EDIT
The solution proposed by Aaron doesn't work either. A snippet:
case class SHA1(sha1: Array[Byte]) {
def unapply(buffer: Array[Byte]) = buffer.length % 2 == 0
}
object Sha1Sample {
def main(args: Array[String]) {
println("Sha1 Sample")
val b1: Array[Byte] = Array(0, 1, 2)
val b2: Array[Byte] = Array(0, 1, 2, 3)
val sha1 = SHA1(b1)
List(b1, b2) map { b =>
b match {
case sha1() => println("Match") // works
case `sha1` => println("Match") // compile but it is semantically incorrect
case SHA1(`b1`) => println("SOLVED") // won't compile
case _ => println("Doesn't Match")
}
}
}
}
Short answer: you need to put backticks around lowercase identifiers if you don't want them to be interpreted as pattern variables.
case Sha1(`sha1`) => // ...
See this question.

Scala: Generalised method to find match and return match dependant values in collection

I wish to find a match within a List and return values dependant on the match. The CollectFirst works well for matching on the elements of the collection but in this case I want to match on the member swEl of the element rather than on the element itself.
abstract class CanvNode (var swElI: Either[CSplit, VistaT])
{
private[this] var _swEl: Either[CSplit, VistaT] = swElI
def member = _swEl
def member_= (value: Either[CSplit, VistaT] ){ _swEl = value; attach}
def attach: Unit
attach
def findVista(origV: VistaIn): Option[Tuple2[CanvNode,VistaT]] = member match
{
case Right(v) if (v == origV) => Option(this, v)
case _ => None
}
}
def nodes(): List[CanvNode] = topNode :: splits.map(i => List(i.n1, i.n2)).flatten
//Is there a better way of implementing this?
val temp: Option[Tuple2[CanvNode, VistaT]] =
nodes.map(i => i.findVista(origV)).collectFirst{case Some (r) => r}
Do I need a View on that, or will the collectFirst method ensure the collection is only created as needed?
It strikes me that this must be a fairly general pattern. Another example could be if one had a List member of the main List's elements and wanted to return the fourth element if it had one. Is there a standard method I can call? Failing that I can create the following:
implicit class TraversableOnceRichClass[A](n: TraversableOnce[A])
{
def findSome[T](f: (A) => Option[T]) = n.map(f(_)).collectFirst{case Some (r) => r}
}
And then I can replace the above with:
val temp: Option[Tuple2[CanvNode, VistaT]] =
nodes.findSome(i => i.findVista(origV))
This uses implicit classes from 2.10, for pre 2.10 use:
class TraversableOnceRichClass[A](n: TraversableOnce[A])
{
def findSome[T](f: (A) => Option[T]) = n.map(f(_)).collectFirst{case Some (r) => r}
}
implicit final def TraversableOnceRichClass[A](n: List[A]):
TraversableOnceRichClass[A] = new TraversableOnceRichClass(n)
As an introductory side node: The operation you're describing (return the first Some if one exists, and None otherwise) is the sum of a collection of Options under the "first" monoid instance for Option. So for example, with Scalaz 6:
scala> Stream(None, None, Some("a"), None, Some("b")).map(_.fst).asMA.sum
res0: scalaz.FirstOption[java.lang.String] = Some(a)
Alternatively you could put something like this in scope:
implicit def optionFirstMonoid[A] = new Monoid[Option[A]] {
val zero = None
def append(a: Option[A], b: => Option[A]) = a orElse b
}
And skip the .map(_.fst) part. Unfortunately neither of these approaches is appropriately lazy in Scalaz, so the entire stream will be evaluated (unlike Haskell, where mconcat . map (First . Just) $ [1..] is just fine, for example).
Edit: As a side note to this side note: apparently Scalaz does provide a sumr that's appropriately lazy (for streams—none of these approaches will work on a view). So for example you can write this:
Stream.from(1).map(Some(_).fst).sumr
And not wait forever for your answer, just like in the Haskell version.
But assuming that we're sticking with the standard library, instead of this:
n.map(f(_)).collectFirst{ case Some(r) => r }
I'd write the following, which is more or less equivalent, and arguably more idiomatic:
n.flatMap(f(_)).headOption
For example, suppose we have a list of integers.
val xs = List(1, 2, 3, 4, 5)
We can make this lazy and map a function with a side effect over it to show us when its elements are accessed:
val ys = xs.view.map { i => println(i); i }
Now we can flatMap an Option-returning function over the resulting collection and use headOption to (safely) return the first element, if it exists:
scala> ys.flatMap(i => if (i > 2) Some(i.toString) else None).headOption
1
2
3
res0: Option[java.lang.String] = Some(3)
So clearly this stops when we hit a non-empty value, as desired. And yes, you'll definitely need a view if your original collection is strict, since otherwise headOption (or collectFirst) can't reach back and stop the flatMap (or map) that precedes it.
In your case you can skip findVista and get even more concise with something like this:
val temp = nodes.view.flatMap(
node => node.right.toOption.filter(_ == origV).map(node -> _)
).headOption
Whether you find this clearer or just a mess is a matter of taste, of course.