0

I have various types of strings like the following:

sales_data_type
saledatatypes
sales_data.new.metric1
sales_data.type.other.metric2
sales_data.type3.metric3

I'm trying to parse them to get a substring with a word before and after the last dot. For example: new.metric1, other.metric2, type3.metric3. If a word doesn't contain dots, it has to be returned as is: sales_data_type, saledatatypes. With a Regex it may be done this way:

val infoStr = "sales_data.type.other.metric2"
val pattern = ".*?([^.]+\\.)?([^.]+)$"  
println(infoStr.replaceAll(pattern, "$1$2"))
// prints other.metric2
// for saledatatypes just prints nullsaledatatypes ??? but seems to work 

I want to find a way to achieve this with Scala, without using Regex in order to expand my understanding of Scala features. Will be grateful for any ideas.

5 Answers 5

3

One-liner:

dataStr.split('.').takeRight(2).mkString(".")

takeRight(2) will take the last 2 if there are 2 to take, else it will take the last, and only, 1. mkString(".") will re-insert the dot only if there are 2 elements for the dot to go between, else it will leave the string unaltered.

Sign up to request clarification or add additional context in comments.

Comments

2

Here's one with lots of scala features for you.

val string = "head.middle.last"

val split = string.split('.') // Array(head, middle, last)

val result = split.toSeq match {
  case Seq(word) ⇒ word
  case _ :+ before :+ after ⇒ s"$before.$after"
}

println(result) // middle.last

First we split the string on your . and get individual parts.
Then we pattern match those parts, first to check if there is only one (in which case we just return it), and second to grab the last two elements in the seq.
Finally we put a . back in between those last two using string interpolation.

Comments

2

One way of doing it:

val value = "sales_data.type.other.metric2"
val elems = value.split("\\.").toList

elems match {
  case _:+beforeLast:+last => s"${beforeLast}.${last}"
  case _ => throw new NoSuchElementException
}

Comments

1
for(s<-strs) yield {val s1 = s.split('.');
     if(s1.size>=2)s1.takeRight(2).mkString(".") else s }

or

for(s<-strs) yield { val s1 = s.split('.');
    if(s1.size>=2)s1.init.last+'.'+s1.last else s }

In Scala REPL:

scala> val strs =
Vector("sales_data_type","saledatatypes","sales_data.new.metric1","sales_data.type.other.metric2","sales_d
ata.type3.metric3")
strs: scala.collection.immutable.Vector[String] = Vector(sales_data_type, saledatatypes, sales_data.new.metric1, sales_data.
type.other.metric2, sales_data.type3.metric3)


scala> for(s<-strs) yield { val s1 = s.split('.');if(s1.size>=2)s1.takeRight(2).mkString(".") else s }
res62: scala.collection.immutable.Vector[String] = Vector(sales_data_type, saledatatypes, new.metric1, other.metric2, type3.
metric3)

scala> for(s<-strs) yield { val s1 = s.split('.');if(s1.size>=2)s1.init.last+'.'+s1.last else s }
res60: scala.collection.immutable.Vector[String] = Vector(sales_data_type, saledatatypes, new.metric1, other.metric2, type3.
metric3)

Comments

1

Use scala match and do like this

def getFormattedStr(str:String):String={
  str.contains(".") match{
    case true=>{
      val arr=str.split("\\.")
      val len=arr.length
      len match{
        case 1=>str
        case _=>arr(len-2)+"."+arr(len-1)
      }
    }
    case _=>str
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.