# A scala implementation of the Java trim method

I'm a Scala beginner and looking at the trim() method of the Java API. I noticed side effects, so I attempted to implement a functional version in Scala.

Here is the Java version:

public String trim() {
int len = count;
int st = 0;
int off = offset;      /* avoid getfield opcode */
char[] val = value;    /* avoid getfield opcode */

while ((st < len) && (val[off + st] <= ' ')) {
st++;
}
while ((st < len) && (val[off + len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < count)) ? substring(st, len) : this;
}


My Scala version iterates over a string, and when it encounters a space char, the tail of the string is returned. The entire string is then reversed, so it can access the trailing whitespace. This new string is iterated over until a space char is encountered and the tail of this string is returned. This new string is then reversed again to maintain the original string order:

def trim(stringToTrim : String) : String = {
def removePreString[String](list : List[String]) : java.lang.String = list match {

case head :: tail => {
removePreString(tail)
}
else {
}
}
}//end removePreString

val preString =    removePreString(stringToTrim.toList)
val reveresedString = preString.toList.reverse
val reveresedPostString = removePreString(reveresedString)
reveresedPostString.reverse

}//end trim


How can this code be improved? Does it seem wasteful reversing the string twice?

-

No good idea about the concern of reversing the list twice. But you may

1. Let you inner function return a List instead of a string thus having less conversions from list to string and string to list.

2. Change your match to the following pattern (not tested):

case " " :: tail => removePreString(tail)
case _ => _


I just realize you could also use on a list def dropWhile(p: (A) ⇒ Boolean): List[A] which drops longest prefix of elements that satisfy a predicate. You could then chain dropWhile not a space | reverse | dropwhile not a space | reverse...

-

you can test for a whitespace in patter matching, an alternative version of your removePreSign method therefore could be written as:

def removePreString(list : List[Char]): String = list match {
case ' ' :: tail => removePreString(tail)
case _ => list.mkString
}


but as pgras noted, you can simply use str.dropWhile(_ == ' ') which avoids the whole String <=> List issue.

A possible way to do it without reverse and dropWhile using only recursion:

def trim(stringToTrim : String) : String = {
if (str startsWith " " ) removeLeading(str tail)
else str

def removeTrailing(str: String): String =
if (str endsWith " ") removeTrailing(str dropRight 1 )
else str

}

-
your function 'removePreString' does not work for Strings with trailing whitespace. e.g - " this is a test " – blue-sky Jan 14 '13 at 21:38
neither does the original function, it is just another way to achieve the same thing, but as noted above it is equivalent to dropWhile – Markus Hauck Jan 15 '13 at 9:31
• Since left and right trim may be useful on their own, expose them.
• View String as a list of Char instead of converting to List[String]
• The recursion creates a string at each step ! Take advantage of the rich library of methods for lists (and the like).
• For instance, reversing twice is fine as long you manipulate iterators.

def trimLeft  (s: String) = s dropWhile ( _ == ' ' )
def trimRight (s: String) = (s.reverseIterator dropWhile ( _ == ' ' ))
.toSeq.reverseIterator mkString
val trim = trimLeft _ compose trimRight _


It you prefer to extract the sub-string of interest at once, there are fine functions to find the indices you need.

-