Take first three letters in the string - scala

I need to retrieve first three letters
val s ="abc"
val t = s.substring(0,2).equals("ab")
case class Test(id :String)
if(t){
Test("found")
}else{
None
}
Is there a efficient way to code for the above logic

"abc".take(2) match {
case "ab" => Test("found")
case _ => None
}
for String, you can use take to get chars like Seq, and it's more safe than substring to avoid StringIndexOutOfBoundsException exception.
and since you are returning None when not match, Test("found") Shouldn't be Some(Test("found"))?

One-liner:
case class Test(id: String)
val s = "abc"
if (s.take(2) == "ab") Test("found") else None
Make sure your string is at least 2 characters long or take will throw an exception.

Related

Typecasting in Scala

I have an alphanumeric field in an RDD of type AnyRef.
Case1: If it's 99898, I want to cast it as Long
Case2: If it's 0099898, I want to cast it as String
Case3: If it's AB998, I want to cast it as String.
I am trying this:
try {
account_number.asInstanceOf[ Long ])
} catch {
case _: Throwable => account_number.asInstanceOf[ String ])
}
But in this, I miss the case2, because 0099898 is converted to 99898. Any ideas?
If this field is AnyRef I wouldn't expect AnyVals there at all (like Long) - Scala's numbers are not equal to Java's numbers. At best you can have there some instance of java.lang.Numeric (e.g. java.lang.Long which is NOT scala.Long).
But to turn it into Long you would have to use pattern matching (with type matching or regexp pattern matching) and conversion (NOT casting!) to
val isStringID = raw"(0[0-9]+)".r
val isLongID = raw"([0-9]+)".r
account_number match {
case isStringID(id) => id // numeric string starting with 0
case isLongID(id) => id.toLong // numeric string convertible to Long
case l: java.lang.Long => l.toLong // Java's long
case _ => throw new IllegalArgumentException("Expected long or numeric string")
}
However, I would find that completely useless - right now you have Any instead of AnyVal. You could expect it to have Long or String but it's not represented by the returned value so compiler would NOT have any information about the safe usages. Personally, I would recommend doing something imediatelly after matching e.g. wrapping it with Either or creating ADT or passing it to function which needs String or Long.
// can be exhaustively pattern matched, or .folded or passed, etc
val stringOrLong: Either[String, Long] = account_number match {
case isStringID(id) => Left(id)
case isLongID(id) => Right(id.toLong)
case l: java.lang.Long => Right(l.toLong)
case _ => throw new IllegalArgumentException("Expected long or numeric string")
}
You cannot use .asInstanceOf to turn AnyRef to Long because neither is subtype or supertype of another, and this operation would always fail.
Any
/ \
AnyVal AnyRef
| |
Long |
\ /
Nothing
.asInstanceOf would only make sense if you were moving vertically in this hierarchy, not horizontally.
Another option you have is:
def tryConvert(s: String): Either[Long, String] = {
Try(s.toLong).filter(_.toString == s) match {
case Success(value) =>
Left(value)
case Failure(_) =>
Right(s)
}
}
Code run at Scastie.

Scala Pattern Matching using Option[Type]

I am playing around with Scala at the moment and the pattern matching. I have the general idea behind it and can get the basics working. My issue is with Option[]. It is possible to use pattern matching on Option[]'s?
What I am trying to do is make a little function that will take in an option[String] parameter and then based on the input return the string if its a string and a heads up if not. I am not too sure on how to go about this though, I have tried a few thing but it either gives out or in the case below will never hit the second case.
def getString(someString: Option[String]): String =
someString match {
case s: Option[String] => someString //also tried things like case: String => ...
case _ => s"no string entered" //and things like case _ => ...
}
This is the easiest way to implement your function:
def getString(someString: Option[String]): String =
someString.getOrElse("no string entered")
If you want to use match it looks like this:
def getString(someString: Option[String]): String =
someString match {
case Some(s) => s
case _ => "no string entered"
}

Scala: string pattern matching

The below code takes the first two character of string and check if pattern is "de" or None it returns None else it returns the Test("Found")
val s =Option("abc")
val t = s.map(_.take(2))
case class Test(id:String)
t match {
case Some("de") => None
case None => None
case _ => Test("Found")
}
Can anyone suggest a efficient solution for case matching
I think I get what you're asking so let me try this:
val condition = Option("abc").exists(_.toLower.take(2) == "de")
val output: Any = if(condition) Test("found") else None
The first portion returns false if the Option is None. It also returns false if the first two letters of the string are "de" in a case insensitive way.
The second portion returns either a None or a Test object. However, I want to point out that this results in an Any. Did you mean for it to return a Option[Test] type instead?
I assume, you meant Some(Test("Found")) in the last line of your snippet, judging from your comment to the other answer.
If so, this is what you are looking for:
t.filterNot(_.take(2) == "de").map(_ => Test("Found"))

How to pattern match on List('(', List[Char],')')?

I am struggling a bit with some pattern matching on a List[Char]. I would like to extract sub-lists that are enclosed by parentheses. So, I would like to extract "test" as a List[Char] when given "(test)". So basically a match on List('(', List[Char],')'). I am able to match on List('(',t,')') where t is a single character, but not a variable amount of characters.
How should this be declared?
val s = "(test)"
s match {
case List('(',t,')') => {
println("matches single character")
}
case '('::x::y => {
//x will be the first character in the List[Char] (after the '(') and y the tail
}
}
s match {
case '(' +: t :+ ')' => ...
}
Read about custom extractors in Scala and then see http://www.scala-lang.org/api/2.11.8/index.html#scala.collection.$colon$plus$ to understand how it works.
Note that it'll match any suitable Seq[Char], but a string isn't really one; it can only be converted (implicitly or explicitly). So you can use one of
val s: Seq[Char] = ...some String or List[Char]
val s = someString.toSeq
I expect that performance for String should be good enough (and if it's critical, don't use this); but for large List[Char] this will be quite slow.

Retrieve tuple from string

I have the following input string:
"0.3215,Some(0.5123)"
I would like to retrieve the tuple (0.3215,Some(0.5123)) with: (BigDecimal,Option[BigDecimal]).
Here is one of the thing I tried so far:
"\\d+\\.\\d+,Some\\(\\d+\\.\\d+".r findFirstIn iData match {
case None => Map[BigDecimal, Option[BigDecimal]]()
case Some(s) => {
val oO = s.split(",Some\\(")
BigDecimal.valueOf(oO(0).toDouble) -> Option[BigDecimal](BigDecimal.valueOf(lSTmp2(1).toDouble))
}
}
Using a Map and transforming it into a tuple.
When I try directly the tuple I get an Equals or an Object.
Must miss something here...
Your code has several issues, but the big one seems to be that the case None side of the match returns a Map but the Some(s) side returns a Tuple2. Map and Tuple2 unify to their lowest-common-supertype, Equals, which is what you're seeing.
I think this is what you're trying to achieve?
val Pattern = "(\\d+\\.\\d+),Some\\((\\d+\\.\\d+)\\)".r
val s = "0.3215,Some(0.5123)"
s match {
case Pattern(a,b) => Map(BigDecimal(a) -> Some(BigDecimal(b)))
case _ => Map[BigDecimal, Option[BigDecimal]]()
}
// Map[BigDecimal,Option[BigDecimal]] = Map(0.3215 -> Some(0.5123))