Is there an easy/best way to get a BitSet I can pattern match like a list?
val btst = BitSet(1,2,3,4)
btst match {
...
case head :: tail => tail
}
By definition a set is an unordered collection, and pattern matching over such one is error-prone. Convert it to list if you want to... Also, you should not rely on head and tail to always return the same thing.
A BitSet is ordered, but extractorless.
Edit: but not humorless.
object |<| {
def unapply(s: BitSet): Option[(Int, BitSet)] =
if (s.isEmpty) None
else Some((s.head, s.tail))
}
def flags(b: BitSet) = b match {
case f"5 || 10" => println("Five and dime") // alas, never a literal
case 5 |<| any => println(s"Low bit is 5iver, rest are $any")
case i |<| any => println(s"Low bit is $i, rest are $any")
case _ => println("None")
}
def dump(b: BitSet) = println(b.toBitMask.mkString(","))
val s = BitSet(5, 7, 11, 17, 19, 65)
dump(s)
// ordinary laborious tests
s match {
case x if x == BitSet(5) => println("Five")
case x if x == BitSet(5,7,11,17,19,65) => println("All")
case x if x(5) => println("Five or more")
case _ => println("None")
}
// manually matching on the mask is laborious
// and depends on the bit length
s.toBitMask match {
case Array(2L) => println("One")
case Array(657568L) => println("First word's worth")
case Array(657568L, _) => println("All")
case _ => println("None")
}
// or truncate for special case
s.toBitMask(0) match {
case 2L => println("One")
case 657568L => println("First word's worth")
case _ => println("None")
}
Related
def checkPeq[A,B](list1: List[(A, List[B])])( P: (A,B) => Boolean): List[Boolean] = {
def helper[A,B](list2: List[(A, List[B])], list3: List[B], acc1: Boolean, acc2: List[Boolean])(leq:(A,B) => Boolean): List[Boolean] = {
list2 match {
case h1::t1 => {
list3 match {
case Nil if t1!=Nil => helper(t1, t1.head._2, true, acc1::acc2)(leq)
case Nil => (acc1::acc2).reverse
case h2::t2 if(leq(h1._1, h2)) => helper(list2, t2, acc1, acc2)(leq)
case h2::t2 => helper(list2, t2, false, acc2)(leq)
}
}
}
}
helper(list1, list1.head._2, true, List())(P)
}
val list1 = List((1,List(1,2,3)), (2, List(2,3)), (3, List(3,2)), (4, List(4,5,6,3)))
println(checkPeq(list1)(_<=_))
I have a tail recursive function which returns List[Boolean], in this case List(true, true, false, false). It's working, but the problem is I need to do it without ._ or .head and preferably without indexes(bcz I can easily replace .head in this function with (0)). I need to do it with pattern matching and I don't have an idea how to start. I also got a tip from my teacher replacing it should be pretty fast. I'd appreciate any tips on how to deal with the problem.
One solution is to simply pattern match both the outer A list and the inner B list at the same time, i.e. as part of a single pattern.
def checkPeq[A,B](in: List[(A,List[B])])(pred: (A,B) => Boolean): List[Boolean] = {
#annotation.tailrec
def loop(aLst :List[(A,List[B])], acc :List[Boolean]) :List[Boolean] =
aLst match {
case Nil => acc.reverse //A list done
case (_,Nil) :: aTl => loop(aTl, true::acc) //B list done
case (a,b::bTl) :: aTl => //test a and b
if (pred(a,b)) loop((a,bTl) :: aTl, acc)
else loop(aTl, false::acc)
}
loop(in, List.empty[Boolean])
}
Here are missing pieces that should help you solve the rest of the problem:
Pattern matching a list
val l = List(2,3)
l match {
case Nil => "the list is empty"
case head :: Nil => "the least has one element"
case head :: tail => "thie list has a head element and a tail of at least one element"
}
Pattern matching a tuple
val t = (75, "picard")
t match {
case (age, name) => s"$name is $age years old"
}
Pattern matching a list of tuples
val lt = List((75, "picard"))
lt match {
case Nil => "the list is empty"
case (name, age) :: Nil => "the list has one tuple"
case (name, age) :: tail => "the list has head tuple and a tail of at least another tuple"
}
Pattern matching a tuple of list of tuples
val lt = List((75, "picard"))
val ct = List((150, "Data"))
(lt, ct) match {
case (Nil, Nil) => "tuple of two empty lists"
case ((name, age) :: Nil, Nil) => "tuple of a list with one tuple and another empty list"
case (Nil, (name, age) :: Nil) => "tuple of an empty list and another list with one tuple"
case ((name, age) :: tail, Nil) => "tuple of list with head tuple and a tail of at least another tuple, and another empty list"
case _ => "and so on"
}
Note how patterns can be composed.
How to make a string with comma separated by removing Some
case class Animal(name:Option[String], size:Option[Int]=None)
val animal = Animal(Some("apple"),Some(67))
val result = animal.productIterator.mkString(",").toString
//this gives: "Some(apple),Some(67)"
//How to get : "apple,67"
The solution of Pritish misses the None cases.
For example: Animal(Some("apple"),None) //returns apple,None
So If you are not happy with None int the list you can either replace it with a String or filter them out:
As String:
val result = animal.productIterator.map {
case Some(x) => x
case None => "[no value]"
case x => x // only needed if you would have non optional values
}.mkString(",") // > apple,[no value]
Filter them:
val result = animal.productIterator.map {
case Some(x) => x
case x => x
}.filter{
case None => false
case _ => true
}.mkString(",") // > apple
Try this:
val result = animal.productIterator.map {
case Some(x) => x
case x => x
}.mkString(",")
There is a list with type List[Option[String]], it may contain Some or None
val list:List[Option[String]] = List(Some("aaa"), None, Some("bbb"))
list match {
case /*List with all Some*/ => println("all items are Some")
case /*List with all None*/ => println("all items are None")
case /*List with Some and None*/ => println("Contain both Some and None")
}
But I don't know how to write it. Is it possible to use pattern matching?
You can write custom extractors:
object AllSome {
def unapply[T](l: List[Option[T]]) = l.forall(_.isDefined)
}
object AllNone {
def unapply[T](l: List[Option[T]]) = l.forall(_ == None)
}
object Mixed {
def unapply[T](l: List[Option[T]]) = !AllNone.unapply(l) && !AllSome.unapply(l)
}
And use them like:
list match {
case AllSome() => ???
case AllNone() => ???
case Mixed() => ???
}
One approach involves flattening the list and comparing the resulting length with the original length, like this,
list.flatten.length match {
case 0 => println("All items are None")
case len if len < l.length => println("Contain both Some and None")
case _ => println("All items are Some")
}
Update
To get the contents of each Some, simply list.flatten , namely for instance,
list.flatten
res: List(aaa, bbb)
and
List().flatten
res: List[Nothing] = List()
If you really want a solution with well-defined semantics and based on pattern matching you could do something as follows:
abstract class CollectionStatus
case object Empty extends CollectionStatus
case object AllSome extends CollectionStatus
case object AllNone extends CollectionStatus
case object Mixed extends CollectionStatus
object CollectionStatus {
def default: CollectionStatus = Empty
}
def folder(status: CollectionStatus, o: Option[_]): CollectionStatus = {
(status, o) match {
case (Empty, Some(_)) => AllSome
case (Empty, None) => AllNone
case (AllSome, Some(_)) => AllSome
case (AllNone, None) => AllNone
case _ => Mixed
}
}
Here's how I would use it:
List[Option[String]]().foldLeft(CollectionStatus.default)(folder _) //Empty
List(Option("foo"), Option("bar")).foldLeft(CollectionStatus.default)(folder _) //AllSome
List(Option("foo"), None).foldLeft(CollectionStatus.default)(folder _) //Mixed
List(None, None).foldLeft(CollectionStatus.default)(folder _) //AllNone
This could be further improved by replacing foldLeft with a tail recursive function that would accumulate the status of the list, and finish its computations without traversing the whole list if it recognized the list was "Mixed" already:
import scala.annotation.tailrec
def listStatus(list: List[Option[_]]): CollectionStatus = {
#tailrec
def inner(acc: CollectionStatus, ls: List[Option[_]]): CollectionStatus = {
acc match {
case Mixed => Mixed
case s => {
ls match {
case Nil => s
case h :: t => {
inner(folder(s, h), t)
}
}
}
}
}
inner(CollectionStatus.default, list)
}
val l: List[Option[String]] = List(Some("aaa"), None, Some("bbb"))
l.groupBy({
case Some(_) => "s"
case None => "n"
}).toList match {
case List(_,_) => println("both")
case List(a) => if( a._1 == "n") println("none") else println("some")
}
I have the following code:
class CSplit(var s1: CanvNode, var s2: CanvNode) extends SplitPane
{
topComponent = s1.merge
bottomComponent = s2.merge
def containsV(orig: MapCanvT): Option[MapCanvT] =
{
def containsIn(cn: CanvNode): Option[MapCanvT] = cn match
{
case Left => None
case Right(mc) => if (mc == orig) Some(mc) else None
}
containsIn(s1) match
{
case Some(mc) => Some(mc)
case None => containsIn(s2)
}
}
}
I want to reduce the code of the containsV method. My first thought was to use a fold method to shorten the containsIn method. But Option doesn't have one, nor does it extend Class Either. Shouldn't Option[T] extend Either[T, None] ? Then at least one could use Either's fold method.
My final thought was to treat s1 and s2 as a List and do find over it but I can't get this to compile:
def containsV(orig: MapCanvT):
Option[MapCanvT] = ::[CanvNode](s1, s2).find(_ == Right(orig))
Scala 2.10 adds fold to Option. In the meantime you can use map(f).getOrElse(g) instead:
// These produce identical results
o.fold(g)(x => f(x))
o.map(x => f(x)).getOrElse(g)
Edit: so, for example, the following three do the same thing:
val os: List[Option[Int]] = List(Some(5),None)
// Explicit match
os.map{ _ match {
case Some(x) => x+3
case None => 0
}}
// map+getOrElse
os.map{ _.map(_+3).getOrElse(0) }
// fold
os.map{ _.fold(0)(_+3) }
In the fold case, you give the default value for the None case first, and then the function that handles the case where there is a value. In each case you should get List(8,0).
It can be implemented with a list by using the collectFirst method
def containsV(orig: MapCanvT): Option[MapCanvT]
= List(s1, s2).collectFirst {case i: MapCanvT if (i == (orig) => i}
Let's start with the easy part:
containsIn(s1) match
{
case Some(mc) => Some(mc)
case None => containsIn(s2)
}
is the same as
containsIn(s1) orElse containsIn(s2)
Now we only have to deal with containsIn:
def containsIn(cn: CanvNode): Option[MapCanvT] = cn match
{
case Left => None
case Right(mc) => if (mc == orig) Some(mc) else None
}
We can use fold on Either, which gets rid of most of the pattern matching:
cn.fold(_ => None, Some(_))
But there's the orig thingy. We can handle it with a filter, though:
cn.fold(_ => None, Some(_)) filter (orig.==)
Thus:
def containsV(orig: MapCanvT): Option[MapCanvT] = {
def containsIn(cn: CanvNode): Option[MapCanvT] =
cn.fold(_ => None, Some(_)) filter (orig.==)
containsIn(s1) orElse containsIn(s2)
}
I think orElse is much overlooked.
I'm often writing code that compares two objects and produces a value based on whether they are the same, or different, based on how they are different.
So I might write:
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case (Some(value), None)) => "b"
case (None, Some(value)) => "b"
case _ = > "c"
}
Those 2nd and 3rd cases are the same really, so I tried writing:
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case (Some(value), None)) || (None, Some(value)) => "b"
case _ = > "c"
}
But no luck.
I encounter this problem in a few places, and this is just a specific example, the more general pattern is I have two things, and I want to know if one and only one of them meet some predicate, so I'd like to write something like this:
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case OneAndOnlyOne(value, v: Option[Foo] => v.isDefined ) => "b"
case _ = > "c"
}
So the idea here is that OneAndOnlyOne can be configured with a predicated (isDefined in this case) and you can use it in multiple places.
The above doesn't work at all, since its backwards, the predicate needs to be passed into the extractor not returned.
How about something like this?
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case new OneAndOnlyOne(v: Option[Foo] => v.isDefined )(value) => "b"
case _ = > "c"
}
with:
class OneAndOnlyOne[T](predicate: T => Boolean) {
def unapply( pair: Pair[T,T] ): Option[T] = {
val (item1,item2) = pair
val v1 = predicate(item1)
val v2 = predicate(item2)
if ( v1 != v2 )
Some( if ( v1 ) item1 else item2 )
else
None
}
}
But, this doesn't compile.
Can anyone see a way to make this solution work? Or propose another solution? I'm probably making this more complicated than it is :)
I think you're asking two slightly different questions.
One question is how to use "or" in switch statements. || doesn't work; | does. And you can't use variables in that case (because in general they might match different types, which renders the type confusing). So:
def matcher[T](a: (T,T)) = {
a match {
case (Some(x),Some(y)) => "both"
case (Some(_),None) | (None,Some(_)) => "either"
case _ => "none"
}
}
Another question is how to avoid having to do this over and over, especially if you want to be able to get at the value in the tuple. I've implemented a version here for Option, but you could use an unwrapped tuple and a boolean.
One trick to achieve this is that to prewrap the values before you start matching on it, and then use your own matching constructs that do what you want. For instance,
class DiOption[+T] {
def trinary = this
}
case class Both[T](first: T, second:T) extends DiOption[T] { }
case class OneOf[T](it: T) extends DiOption[T] { }
case class Neither() extends DiOption[Nothing] { }
implicit def sometuple2dioption[T](t2: (Option[T],Option[T])): DiOption[T] = {
t2 match {
case (Some(x),Some(y)) => Both(x,y)
case (Some(x),None) => OneOf(x)
case (None,Some(y)) => OneOf(y)
case _ => Neither()
}
}
// Example usage
val a = (Some("This"),None)
a trinary match {
case Both(s,t) => "Both"
case OneOf(s) => "Just one"
case _ => "Nothing"
}
If you have to support arbitrary predicates you can derive from this (which is based on Daniel's idea):
List(v1, v2) filter (_ %2 == 0) match {
case List(value1, value2) => "a"
case List(value) => "b"
case _ => "c"
}
the definition of the function:
def filteredMatch[T,R](values : T*)(f : T => Boolean)(p: PartialFunction[List[T], R]) : R =
p(List((values filter f) :_* ))
Now you can use it like this:
filteredMatch(v1,v2)(_ %2 == 0){
case List(value1, value2) => "a"
case List(value) => "b"
case _ => "c"
}
I'm not so sure if it's a good idea (i.e. readable). But a neat exercise nonetheless.
It would be nice if you could match on tuples: case (value1, value2) => ... instead of lists.
How about this:
Welcome to Scala version 2.8.0.r20327-b20091230020149 (Java HotSpot(TM) Client VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def m(v1: Any,v2: Any) = (v1,v2) match {
| case (Some(x),Some(y)) => "a"
| case (Some(_),None) | (None,Some(_)) => "b"
| case _ => "c"
| }
m: (v1: Any,v2: Any)java.lang.String
scala> m(Some(1),Some(2))
res0: java.lang.String = a
scala> m(Some(1),None)
res1: java.lang.String = b
scala> m(None,None)
res2: java.lang.String = c
scala>
You should be able to do it if you define it as a val first:
val MyValThatIsCapitalized = new OneAndOnlyOne(v: Option[Foo] => v.isDefined )
val result = (v1,v2) match {
case (Some(value1), Some(value2)) => "a"
case MyValThatIsCapitalized(value) => "b"
case _ = > "c"
}
As implied by the name, the name of the val containing the extractor object must be capitalized.
On Scala 2.8:
val result = List(v1,v2).flatten match {
case List(value1, value2) => "a"
case List(value) => "b"
case _ = > "c"
}
On Scala 2.7, however, you need a type hint to make it work. So, assuming value is Int, for instance, then:
val result = (List(v1,v2).flatten : List[Int]) match {
case List(value1, value2) => "a"
case List(value) => "b"
case _ = > "c"
}
The funny thing about it is that I misread "first" as "list" on Mitch Blevins answer, and that gave me this idea. :-)
Since you already matched against (Some(x), Some(y)), you may match against (None, None) explicitly, and the remaining cases are (Some(x), None) and (None, Some(y)):
def decide [T](v1: Option[T], v2:Option[T]) = (v1, v2) match {
case (Some (x), Some (y)) => "a"
case (None, None) => "c"
case _ => "b"
}
val ni : Option [Int] = None
decide (ni, ni) // c
decide (Some (4), Some(3)) // a
decide (ni, Some (3)) // b
decide (Some (4), ni) // b