Sunday, January 13, 2008

Augmenting JavaScript's String Object

A popular question to ask in interviews is string manipulation. In particular, string reversal questions are very popular.

Given a string,
  1. Reverse the string
  2. Reverse the words in the string
  3. Reverse only the words in the string
With JavaScript, all three are easy to do. One way to solve it is to augment the String object. In other words, we'll add three new functions to String. We'll call them
  1. reverseString()
  2. reverseWords()
  3. reverseOnlyWords()
To add the methods to String, we'll add them to the String's prototype property so that every instance of a String object or a string primitive will have access to these three methods.

Our definitions look like this

String.prototype.reverseString = function() {
var len = this.length, strArray = [], ct = 0;
for (var i=len-1;i>=0;i--) {
strArray[ct++] = this.charAt(i);
}
return strArray.join("");
}

String.prototype.reverseWords = function() {
var arr = this.split(" ");
var s = "";
while (arr.length>0) {
var element = arr.pop();
s += element + " ";
}
return s;
}

String.prototype.reverseOnlyWords = function() {
var arr = this.reverseWords().split(" ");
var s = "";
while (arr.length>0) {
var element = arr.pop().reverseString();
s += element + " ";
}
return s;
}

Remember that Strings are immutable so calling these functions never changes the original string.

So, doing this --

var s = "now is the time to do the work that must be done";
alert(s.reverseString());


results in the alert dialog displaying "enod eb tsum taht krow eht od ot emit eht si won", but if you display the variable s, you'll still see the string "now is the time to do the work that must be done".

Keep in mind that you can also use a string primitive --

alert("now is the time to do the work that must be done".reverseString());

As we noted in a
previous post, the string primitive is converted to the String object.

Here's a test driver for the three functions. Simply type in a string and watch the functions do their thing.




Of course, you don't have to augment the String. You could instead create a singleton String utility that defines the three functions --

var MyStringUtil = {
reverseString:function(str) {

var len = str.length, strArray = [], ct = 0;

for (var i=len-1;i>=0;i--) {

strArray[ct++] = str.charAt(i);

}

return strArray.join("");
},
reverseWords:function(str) {
var arr = str.split(" ");
var s = "";
while (arr.length>0) {
var element = arr.pop();
s += element + " ";
}
return s;
},
reverseOnlyWords:function(str) {
var arr = this.reverseWords(str).split(" ");
var s = "";
while (arr.length>0) {
var element = this.reverseString(arr.pop());
s += element + " ";
}
return s;
}
}

Feel free to use the functions anyway you like. Here's the augmented string, the string utility and the test driver.

Have fun!

No comments: