tkachuko tkachuko - 1 month ago 8
Scala Question

takeRightWhile() method in scala

I might be missing something but recently I came across a task to get last symbols according to some condition. For example I have a string:

"this_is_separated_values_5"
. Now I want to extract
5
as
Int
.

Note: number of parts separated by
_
is not defined.

If I would have a method
takeRightWhile(f: Char => Boolean)
on a string it would be trivial:
takeRightWhile(ch => ch != '_')
. Moreover it would be efficient: a straightforward implementation would actually involve finding the last index of
_
and taking a substring while the use of this method would save first step and provide better average time complexity.

UPDATE: Guys, all the variations of
str.reverse.takeWhile(_!='_').reverse
are quite inefficient as you actually use additional
O(n)
space. If you want to implement method
takeRightWhile
efficiently you could iterate starting from the right, accumulating result in string builder of whatever else, and returning the result. I am asking about this kind of method, not implementation which was already described and declined in the question itself.

Question: Does this kind of method exist in scala standard library? If no, is there method combination from the standard library to achieve the same in minimum amount of lines?

Thanks in advance.

Answer

Possible solution:

str.reverse.takeWhile(_!='_').reverse

Update

You can go from right to left with following expression using foldRight:

str.toList.foldRight(List.empty[Char]) {
  case (item, acc) => item::acc
}

Here you need to check condition and stop adding items after condition met. For this you can pass a flag to accumulated value:

val (_, list) = str.toList.foldRight((false, List.empty[Char])) {
  case (item, (false, list)) if item!='_' => (false, item::list)
  case (_,    (_,     list))              => (true, list)
}
val res = list.mkString.toInt

This solution is even more inefficient then solution with double reverse:

  1. Implementation of foldRight uses combination of List reverse and foldLeft

  2. You cannot break foldRight execution, so you need flag to skip all items after condition met