How to split a string by delimiter from the right?
Asked Answered
L

4

10

How to split a string by a delimiter from the right?

e.g.

scala> "hello there how are you?".rightSplit(" ", 1)
res0: Array[java.lang.String] = Array(hello there how are, you?)

Python has a .rsplit() method which is what I'm after in Scala:

In [1]: "hello there how are you?".rsplit(" ", 1)
Out[1]: ['hello there how are', 'you?']
Ladylove answered 2/4, 2013 at 2:30 Comment(0)
I
16

I think the simplest solution is to search for the index position and then split based on that. For example:

scala> val msg = "hello there how are you?"
msg: String = hello there how are you?

scala> msg splitAt (msg lastIndexOf ' ')
res1: (String, String) = (hello there how are," you?")

And since someone remarked on lastIndexOf returning -1, that's perfectly fine with the solution:

scala> val msg = "AstringWithoutSpaces"
msg: String = AstringWithoutSpaces

scala> msg splitAt (msg lastIndexOf ' ')
res0: (String, String) = ("",AstringWithoutSpaces)
Interstratify answered 2/4, 2013 at 3:2 Comment(4)
lastIndexOf can return -1.Inca
@Inca In which case splitAt will return an empty string first, and the original string second.Interstratify
Dang, you have thought of everything! You are right it works.Inca
unlike the .rsplit() example above, this contains the delimiter, thoughPrevision
K
5

You could use plain old regular expressions:

scala> val LastSpace = " (?=[^ ]+$)"
LastSpace: String = " (?=[^ ]+$)"

scala> "hello there how are you?".split(LastSpace)
res0: Array[String] = Array(hello there how are, you?)

(?=[^ ]+$) says that we'll look ahead (?=) for a group of non-space ([^ ]) characters with at least 1 character length. Finally this space followed by such sequence has to be at the end of the string: $.

This solution wont break if there is only one token:

scala> "hello".split(LastSpace)
res1: Array[String] = Array(hello)
Karisakarissa answered 2/4, 2013 at 8:42 Comment(1)
I thought of suggesting a regular expression, but it's way less efficient and more difficult to understand than the simpler approach I ended up suggesting. Not to cast aspersions on your solution -- which is perfectly workable and different than the others presented --, but I wonder what it is about complex solutions that make people prefer them?Interstratify
E
1
scala> val sl = "hello there how are you?".split(" ").reverse.toList
sl: List[String] = List(you?, are, how, there, hello)

scala> val sr = (sl.head :: (sl.tail.reverse.mkString(" ") :: Nil)).reverse
sr: List[String] = List(hello there how are, you?)
Empathize answered 2/4, 2013 at 19:37 Comment(0)
H
0

I implemented a custom rsplit function in Scala to imitate Python's rsplit.

The concept behind it involves iteratively using lastIndexOf and substring to perform rsplit.

object Main {
  def rsplit(string: String, delimiter: String, maxSplits: Int): Array[String] = {
    var remainingSplits = maxSplits
    var str = string
    var result = List[String]()

    while (remainingSplits > 0) {
      val pos = str.lastIndexOf(delimiter)
      if (pos == -1) {
        result = str :: result
        remainingSplits = 0
        str=""
      } else {
        result = str.substring(pos + delimiter.length) :: result
        str = str.substring(0, pos)
        remainingSplits -= 1
      }
    }

    if (str.nonEmpty || maxSplits == 0) {
      result = str :: result
    }

    result.toArray
  }

  def myPrint(stringArray: Array[String]): Unit= {
    println("["++stringArray.map("\'"++_++"\'").mkString(", ")++"]");
  }

  def main(args: Array[String]): Unit = {
    // Test cases
    myPrint(rsplit("bor tor tor tor", "tor", 2))  // More than maxSplits
    myPrint(rsplit("bor tor tor", "tor", 2))      // Exactly equal to maxSplits
    myPrint(rsplit("bor tor", "tor", 2))      // Less than maxSplits
  }
}

Attempt This Scala code Online!

print("bor tor tor tor".rsplit("tor", 2)) # ['bor tor ', ' ', '']
print("bor tor tor".rsplit("tor", 2))      # ['bor ', ' ', '']
print("bor tor".rsplit("tor", 2))           # ['bor ', '']

Run the reference Python code online!

Hendrik answered 7/5 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.