Can you use a custom string interpolation character in Scala? - string

Scala's string interpolation is pretty straight forward to use:
val user = "Bob"
val message = s"Hello, $user"
//Hello, Bob
For string blocks containing lots of financial data, these normally need double escaping, however (which for large blocks, such as test data, might get long):
val user = "Mary"
val message = s"Balance owing for $user is $100"
//error: invalid string interpolation $1, expected: $$, $identifier or ${expression}
//error: unclosed string literal
val message = s"Balance owing for $user is $$100"
//Balance owing for Mary is $100
Is it possible to use a different interpolation character to avoid the double escape?
val characterA = "Randolph"
val characterB = "Mortimer"
val family = "Duke"
val film = "Trading Places"
val outcome = "wagered"
val message = at"Your property was #{outcome} for $1 by brothers #{characterA} and #{characterB} #{family}"
//Your property was wagered for $1 by brothers Randolph and Mortimer Duke

Is it possible to use a different interpolation character to avoid the double escape?
$ is part of Scala syntax, however it is at least possible to define custom string interpolation along the lines
scala> implicit class DollarSignInterpolation(val sc: StringContext) {
| def usd(args: Any*): String =
| sc.s(args:_*).replace("USD", "$")
| }
class DollarSignInterpolation
scala> val user = "Mary"
val user: String = Mary
scala> usd"""Balance owing for $user is USD100"""
val res0: String = Balance owing for Mary is $100

You can always use the format method:
val message = "Your property was %s for 1$ by brothers %s and %s %s"
println(message.format("actual outcome", "actual characterA", "actual characterB", "actual family"))

Related

How do I split one string into two strings in Kotlin with "."?

Let's say I have this string:
val mainString: String = "AAA.BBB"
And now I define two children strings:
val firstString: String = ""
val secondString: String = ""
What code should I write to make firstString equals to "AAA", and secondString equals to "BBB"?
The below code works for any amount of strings separated by delimiters
val texto = "111.222.333"
val vet = texto.split(".")
for (st in vet) println(st)
It prints
111
222
333

How do I remove a substring/character from a string in Scala?

I am writing a program in which I need to filter a string. So I have a map of characters, and I want the string to filter out all characters that are not in the map. Is there a way for me to do this?
Let's say we have the string and map:
str = "ABCDABCDABCDABCDABCD"
Map('A' -> "A", 'D' -> "D")
Then I want the string to be filtered down to:
str = "BCBCBCBCBC"
Also, if I find a given substring in the string, is there a way I can replace that with a different substring?
So for example, if we have the string:
"The number ten is even"
Could we replace that with:
"The number 10 is even"
To filter the String with the map is just a filter command:
val str = "ABCDABCDABCDABCDABCD"
val m = Map('A' -> "A", 'D' -> "D")
str.filterNot(elem => m.contains(elem))
A more functional alternative as recommended in comments
str.filterNot(m.contains)
Output
scala> str.filterNot(elem => m.contains(elem))
res3: String = BCBCBCBCBC
To replace elements in the String:
string.replace("ten", "10")
Output
scala> val s = "The number ten is even"
s: String = The number ten is even
scala> s.replace("ten", "10")
res4: String = The number 10 is even

Adding single quotes to a string in Scala

we are trying to add single quotes to each element of a set of string's in Scala
val s : Set[String] = Set("abcd","cdef")
Expected outcome is val s : Set[String] = Set("'abcd'","'cdef'")
tried multiple approaches
Approach1:
s.map(x => x.mkString("'", "', '", "'"))
Approach2:
s.map(x => '\'' + x + '\'')
Fairly new to Scala if someone could please point us in the right direction it would be of great help
I don't think there is no big difference between Scala and whichever language you've been using.
One thing you might want to use is String interpolation
and then you can write
s.map(x => s"'$x'")
you cannot similar similar pattern to wrap it with double quotes. So, when it comes to single or double quotes wrapping, go for hex values. hex 22 is for double quotes and hex 27 for single quotes. It will be easy to remember.
scala> val sq = Integer.parseInt("27",16).toChar
sq: Char = '
scala> val dq = Integer.parseInt("22",16).toChar
dq: Char = "
scala> val s : Set[String] = Set("abcd","cdef")
s: Set[String] = Set(abcd, cdef)
scala> s.map(x => s"$sq$x$sq")
res14: scala.collection.immutable.Set[String] = Set('abcd', 'cdef')
scala> s.map(x => s"$dq$x$dq")
res15: scala.collection.immutable.Set[String] = Set("abcd", "cdef")
hope, this adds clarity to such scenarios.

Scala/Spark efficient partial string match

I am writing a small program in Spark using Scala, and came across a problem. I have a List/RDD of single word strings and a List/RDD of sentences which might or might not contain words from the list of single words. i.e.
val singles = Array("this", "is")
val sentence = Array("this Date", "is there something", "where are something", "this is a string")
and I want to select the sentences that contains one or more of the words from singles such that the result should be something like:
output[(this, Array(this Date, this is a String)),(is, Array(is there something, this is a string))]
I thought about two approaches, one by splitting the sentence and filtering using .contains. The other is to split and format sentence into a RDD and use the .join for RDD intersection. I am looking at around 50 single words and 5 million sentences, which method would be faster? Are there any other solutions? Could you also help me with the coding, I seem to get no results with my code (although it compiles and run without error)
You can create a set of required keys, look up the keys in sentences and group by keys.
val singles = Array("this", "is")
val sentences = Array("this Date",
"is there something",
"where are something",
"this is a string")
val rdd = sc.parallelize(sentences) // create RDD
val keys = singles.toSet // words required as keys.
val result = rdd.flatMap{ sen =>
val words = sen.split(" ").toSet;
val common = keys & words; // intersect
common.map(x => (x, sen)) // map as key -> sen
}
.groupByKey.mapValues(_.toArray) // group values for a key
.collect // get rdd contents as array
// result:
// Array((this, Array(this Date, this is a string)),
// (is, Array(is there something, this is a string)))
I've just tried to solve your problem and I've ended up with this code:
def check(s:String, l: Array[String]): Boolean = {
var temp:Int = 0
for (element <- l) {
if (element.equals(s)) {temp = temp +1}
}
var result = false
if (temp > 0) {result = true}
result
}
val singles = sc.parallelize(Array("this", "is"))
val sentence = sc.parallelize(Array("this Date", "is there something", "where are something", "this is a string"))
val result = singles.cartesian(sentence)
.filter(x => check(x._1,x._2.split(" ")) == true )
.groupByKey()
.map(x => (x._1,x._2.mkString(", ") )) // pay attention here(*)
result.foreach(println)
The last map line (*) is there just beacause without it I get something with CompactBuffer, like this:
(is,CompactBuffer(is there something, this is a string))
(this,CompactBuffer(this Date, this is a string))
With that map line (with a mkString command) I get a more readable output like this:
(is,is there something, this is a string)
(this,this Date, this is a string)
Hope it could help in some way.
FF

Split String into alternating words (Scala)

I want to split a String into alternating words. There will always be an even number.
e.g.
val text = "this here is a test sentence"
should transform to some ordered collection type containing
"this", "is", "test"
and
"here", "a", "sentence"
I've come up with
val (l1, l2) = text.split(" ").zipWithIndex.partition(_._2 % 2 == 0) match {
case (a,b) => (a.map(_._1), b.map(_._1))}
which gives me the right results as two Arrays.
Can this be done more elegantly?
scala> val s = "this here is a test sentence"
s: java.lang.String = this here is a test sentence
scala> val List(l1, l2) = s.split(" ").grouped(2).toList.transpose
l1: List[java.lang.String] = List(this, is, test)
l2: List[java.lang.String] = List(here, a, sentence)
So, how about this:
scala> val text = "this here is a test sentence"
text: java.lang.String = this here is a test sentence
scala> val Reg = """\s*(\w+)\s*(\w+)""".r
Reg: scala.util.matching.Regex = \s*(\w+)\s*(\w+)
scala> (for(Reg(x,y) <- Reg.findAllIn(text)) yield(x,y)).toList.unzip
res8: (List[String], List[String]) = (List(this, is, test),List(here, a, sentence))
scala>

Resources