Port PHP’s str_pad to JavaScript
September 3, 2009 – 11:11 pmToday I needed a function that pads a string to a certain length with another string. In PHP this function is called str_pad. Unfortunately JavaScript doesn’t have such function and I decided to write it myself.
Much to my surpise that was interesting becuase in so short and simple function it is possible to make a lot of performance mistakes.
The requirements for this function is the same as for PHP’s function, so it is an analog.
So, how was it ?
When I developed my first version of this function I decided to test it for performance. I’ve developed a small test script that executes this function 3000 times with different parameters. For all tests I used Firefox with Firebug’s Profiler. First test was taking about 1.1 seconds.
I decided to look around for similar solutions. I looked at PHP’s sources and founded there few good ideas. Then I’ve found a very nice site with already ported analog and I tried to test it too
Wow the result was much better than mine. This task was taking about 600ms.
Eventually I merged 3 ideas and I’ve added some tricks about string’s concatenation. I run a test again and now it takes only 147ms.
This function was improved significantly comparing with 1st time. Almost in 10 times.
Here is the source code:
01 String.PAD_LEFT = 0;02 String.PAD_RIGHT = 1;03 String.PAD_BOTH = 2;04 05 String.prototype.str_pad = function(length, string, type)06 {07 if (undefined == type)08 {09 type = String.PAD_RIGHT;10 }11 else if (type < String.PAD_LEFT || type > String.PAD_BOTH)12 {13 return false;14 }15 16 if (undefined == string)17 {18 string = " ";19 }20 21 if (length <= 0 || (this.length - length) >= 0)22 {23 return false;24 }25 26 if ("string" != typeof(string))27 {28 string = new String(string);29 }30 31 var num_pad_chars = length - this.length,32 pad_left = 0,33 pad_right = 0;34 35 switch(type)36 {37 case String.PAD_LEFT:38 pad_left = num_pad_chars;39 pad_right = 0;40 break;41 42 case String.PAD_RIGHT:43 pad_left = 0;44 pad_right = num_pad_chars;45 break;46 47 case String.PAD_BOTH:48 pad_left = Math.floor(num_pad_chars / 2);49 pad_right = num_pad_chars - pad_left;50 break;51 }52 53 var left_mu = Math.ceil(pad_left/string.length);54 var left = [];55 while(left_mu)56 {57 left.push(string);58 left_mu--;59 }60 left = left.join("").substr(0, pad_left);61 62 var right_mu = Math.ceil(pad_right/string.length);63 var right = [];64 while(right_mu)65 {66 right.push(string);67 right_mu--;68 }69 right = right.join("").substr(0, pad_right);70 71 72 return left + this + right;73 }
and some tests:
01 var a = "123456";02 var b = "0";03 04 print(a.str_pad(10, b));05 print(a.str_pad(10, b, String.PAD_LEFT));06 print(a.str_pad(10, b, String.PAD_RIGHT));07 print(a.str_pad(10, b, String.PAD_BOTH));08 09 print("---------------------");10 11 print(a.str_pad(9, b));12 print(a.str_pad(9, b, String.PAD_LEFT));13 print(a.str_pad(9, b, String.PAD_RIGHT));14 print(a.str_pad(9, b, String.PAD_BOTH));15 16 print("--------------------");17 18 var b = "0A";19 print(a.str_pad(9, b));20 print(a.str_pad(9, b, String.PAD_LEFT));21 print(a.str_pad(9, b, String.PAD_RIGHT));22 print(a.str_pad(9, b, String.PAD_BOTH));23 24 print("----------------------");25 26 print(a.str_pad(9, b, 10));27 28 print("----------------------");29 var a = "3";30 var b = 0x18;31 32 print(a.str_pad(9, b));33 34 print("----------------------");35 36 var a = 3; //error, unknown method37 var b = 0x18;38 39 print(a.str_pad(9, b));40 print(a.str_pad(9, b, String.PAD_LEFT));41 print(a.str_pad(9, b, String.PAD_RIGHT));42 print(a.str_pad(9, b, String.PAD_BOTH));

