Is there a JavaScript function that can pad a stri

2018-12-31 13:05发布

问题:

I am in need of a JavaScript function which can take a value and pad it to a given length (I need spaces, but anything would do). I found this:

Code:

String.prototype.pad = function(l, s, t){
    return s || (s = \" \"), (l -= this.length) > 0 ? (s = new Array(Math.ceil(l / s.length)
        + 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2))
        + this + s.substr(0, l - t) : this;
};

Example:

<script type=\"text/javascript\">
//<![CDATA[

var s = \"Jonas\";
document.write(
    \'<h2>S = \'.bold(), s, \"</h2>\",
    \'S.pad(20, \"[]\", 0) = \'.bold(), s.pad(20, \"[]\", 0), \"<br />\",
    \'S.pad(20, \"[====]\", 1) = \'.bold(), s.pad(20, \"[====]\", 1), \"<br />\",
    \'S.pad(20, \"~\", 2) = \'.bold(), s.pad(20, \"~\", 2)
);

//]]>
</script>

But I have no idea what the heck it is doing and it doesn\'t seem to work for me.

回答1:

I found this solution here and this is for me much much simpler:

var n = 123

String(\"00000\" + n).slice(-5); // returns 00123
(\"00000\" + n).slice(-5); // returns 00123
(\"     \" + n).slice(-5); // returns \"  123\" (with two spaces)

And here I made an extension to the string object:

String.prototype.paddingLeft = function (paddingValue) {
   return String(paddingValue + this).slice(-paddingValue.length);
};

An example to use it:

function getFormattedTime(date) {
  var hours = date.getHours();
  var minutes = date.getMinutes();

  hours = hours.toString().paddingLeft(\"00\");
  minutes = minutes.toString().paddingLeft(\"00\");

  return \"{0}:{1}\".format(hours, minutes);
};

String.prototype.format = function () {
    var args = arguments;
    return this.replace(/{(\\d+)}/g, function (match, number) {
        return typeof args[number] != \'undefined\' ? args[number] : match;
    });
};

This will return a time in the format \"15:30\"



回答2:

A faster method

If you are doing this repeatedly, for example to pad values in an array, and performance is a factor, the following approach can give you nearly a 100x advantage in speed (jsPerf) over other solution that are currently discussed on the inter webs. The basic idea is that you are providing the pad function with a fully padded empty string to use as a buffer. The pad function just appends to string to be added to this pre-padded string (one string concat) and then slices or trims the result to the desired length.

function pad(pad, str, padLeft) {
  if (typeof str === \'undefined\') 
    return pad;
  if (padLeft) {
    return (pad + str).slice(-pad.length);
  } else {
    return (str + pad).substring(0, pad.length);
  }
}

For example, to zero pad a number to a length of 10 digits,

pad(\'0000000000\',123,true);

To pad a string with whitespace, so the entire string is 255 characters,

var padding = Array(256).join(\' \'), // make a string of 255 spaces
pad(padding,123,true);

Performance Test

See the jsPerf test here.

And this is faster than ES6 string.repeat by 2x as well, as shown by the revised JsPerf here



回答3:

http://www.webtoolkit.info/javascript_pad.html

/**
*
*  Javascript string pad
*  http://www.webtoolkit.info/
*
**/

var STR_PAD_LEFT = 1;
var STR_PAD_RIGHT = 2;
var STR_PAD_BOTH = 3;

function pad(str, len, pad, dir) {

    if (typeof(len) == \"undefined\") { var len = 0; }
    if (typeof(pad) == \"undefined\") { var pad = \' \'; }
    if (typeof(dir) == \"undefined\") { var dir = STR_PAD_RIGHT; }

    if (len + 1 >= str.length) {

        switch (dir){

            case STR_PAD_LEFT:
                str = Array(len + 1 - str.length).join(pad) + str;
            break;

            case STR_PAD_BOTH:
                var padlen = len - str.length;
                var right = Math.ceil( padlen / 2 );
                var left = padlen - right;
                str = Array(left+1).join(pad) + str + Array(right+1).join(pad);
            break;

            default:
                str = str + Array(len + 1 - str.length).join(pad);
            break;

        } // switch

    }

    return str;

}

It\'s a lot more readable.



回答4:

Here\'s a recursive approach to it.

function pad(width, string, padding) { 
  return (width <= string.length) ? string : pad(width, padding + string, padding)
}

An example...

pad(5, \'hi\', \'0\')
=> \"000hi\"


回答5:

Using the ECMAScript 6 method String#repeat, a pad function is as simple as:

String.prototype.padLeft = function(char, length) { 
    return char.repeat(Math.max(0, length - this.length)) + this;
}

String#repeat is currently supported in Firefox and Chrome only. for other implementation, one might consider the following simple polyfill:

String.prototype.repeat = String.prototype.repeat || function(n){ 
    return n<=1 ? this : (this + this.repeat(n-1)); 
}


回答6:

String.prototype.padStart() and String.prototype.padEnd() are currently TC39 candidate proposals: see github.com/tc39/proposal-string-pad-start-end (only available in Firefox as of April 2016; a polyfill is available).



回答7:

ECMAScript 2017 adds a padStart method to the String prototype. This method will pad a string with spaces to a given length. This method also takes an optional string that will be used instead of spaces for padding.

\'abc\'.padStart(10);         // \"       abc\"
\'abc\'.padStart(10, \"foo\");  // \"foofoofabc\"
\'abc\'.padStart(6,\"123465\"); // \"123abc\"
\'abc\'.padStart(8, \"0\");     // \"00000abc\"
\'abc\'.padStart(1);          // \"abc\"

A padEnd method was also added that works in the same manner.

For browser compatibility (and a useful polyfill) see this link.



回答8:

The key trick in both those solutions is to create an array instance with a given size (one more than the desired length), and then to immediately call the join() method to make a string. The join() method is passed the padding string (spaces probably). Since the array is empty, the empty cells will be rendered as empty strings during the process of joining the array into one result string, and only the padding will remain. It\'s a really nice technique.



回答9:

Using the ECMAScript 6 method String#repeat and Arrow functions, a pad function is as simple as:

var leftPad = (s, c, n) => c.repeat(n - s.length) + s;
leftPad(\"foo\", \"0\", 5); //returns \"00foo\"

jsfiddle

edit: suggestion from the comments:

const leftPad = (s, c, n) => n - s.length > 0 ? c.repeat(n - s.length) + s : s;

this way, it wont throw an error when s.lengthis greater than n

edit2: suggestion from the comments:

const leftPad = (s, c, n) =>{ s = s.toString(); c = c.toString(); return s.length > n ? s : c.repeat(n - s.length) + s; }

this way, you can use the function for strings and non-strings alike.



回答10:

pad with default values

I noticed that i mostly need the padLeft for time conversion / number padding

so i wrote this function

function padL(a,b,c){//string/number,length=2,char=0
 return (new Array(b||2).join(c||0)+a).slice(-b)
}

This simple function supports Number or String as input

default pad is 2 chars

default char is 0

so i can simply write

padL(1);
// 01

if i add the second argument (pad width)

padL(1,3);
// 001

third parameter (pad char)

padL(\'zzz\',10,\'x\');
// xxxxxxxzzz

EDIT @BananaAcid if you pass a undefined value or a 0 length string you get 0undefined..so:

as suggested

function padL(a,b,c){//string/number,length=2,char=0
 return (new Array((b||1)+1).join(c||0)+(a||\'\')).slice(-(b||2))
}

but this can also be achieved in a shorter way.

function padL(a,b,c){//string/number,length=2,char=0
 return (new Array(b||2).join(c||0)+(a||c||0)).slice(-b)
}

works also with:

padL(0)
padL(NaN)
padL(\'\')
padL(undefined)
padL(false)

And if you want to be able to pad in both ways :

function pad(a,b,c,d){//string/number,length=2,char=0,0/false=Left-1/true=Right
return a=(a||c||0),c=new Array(b||2).join(c||0),d?(a+c).slice(0,b):(c+a).slice(-b)
}

which can be written in a shorter way without using slice.

function pad(a,b,c,d){
 return a=(a||c||0)+\'\',b=new Array((++b||3)-a.length).join(c||0),d?a+b:b+a
}
/*

Usage:

pad(
 input // (int or string) or undefined,NaN,false,empty string
       // default:0 or PadCharacter
 // optional
 ,PadLength // (int) default:2
 ,PadCharacter // (string or int) default:\'0\'
 ,PadDirection // (bolean) default:0 (padLeft) - (true or 1) is padRight 
)

*/

now if you try to pad \'averylongword\' with 2 ... thats not my problem.


Said that i give you a tip.

Most of the time if you pad you do it for the same value N times.

Using any type of function inside a loop slows down the loop!!!

So if you just wanna pad left some numbers inside a long list don\'t use functions to do this simple thing.

use something like this:

var arrayOfNumbers=[1,2,3,4,5,6,7],
    paddedArray=[],
    len=arrayOfNumbers.length;
while(len--){
 paddedArray[len]=(\'0000\'+arrayOfNumbers[len]).slice(-4);
}

if you don\'t know how the max padding size based on the numbers inside the array.

var arrayOfNumbers=[1,2,3,4,5,6,7,49095],
    paddedArray=[],
    len=arrayOfNumbers.length;

// search the highest number
var arrayMax=Function.prototype.apply.bind(Math.max,null),
// get that string length
padSize=(arrayMax(arrayOfNumbers)+\'\').length,
// create a Padding string
padStr=new Array(padSize).join(0);
// and after you have all this static values cached start the loop.
while(len--){
 paddedArray[len]=(padStr+arrayOfNumbers[len]).slice(-padSize);//substr(-padSize)
}
console.log(paddedArray);

/*
0: \"00001\"
1: \"00002\"
2: \"00003\"
3: \"00004\"
4: \"00005\"
5: \"00006\"
6: \"00007\"
7: \"49095\"
*/


回答11:

With ES8, there are two options for padding.

You can check them in the documentation.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/String/padStart



回答12:

Taking up Samuel\'s ideas, upward here. And remember an old SQL script, I tried with this:

a=1234;
\'0000\'.slice(a.toString().length)+a;

It works in all the cases I could imagine:

a=     1 result  0001
a=    12 result  0012
a=   123 result  0123
a=  1234 result  1234
a= 12345 result 12345
a=  \'12\' result  0012


回答13:

Here\'s a simple function that I use.

var pad=function(num,field){
    var n = \'\' + num;
    var w = n.length;
    var l = field.length;
    var pad = w < l ? l-w : 0;
    return field.substr(0,pad) + n;
};

For example:

pad    (20,\'     \');    //   20
pad   (321,\'     \');    //  321
pad (12345,\'     \');    //12345
pad (   15,\'00000\');    //00015
pad (  999,\'*****\');    //**999
pad (\'cat\',\'_____\');    //__cat  


回答14:

A short way:

(x=>(new Array(int-x.length+1)).join(char)+x)(String)

Example:

(x=>(new Array(6-x.length+1)).join(\"0\")+x)(\"1234\")

return: \"001234\"



回答15:

es7 is just drafts and proposals right now, but if you wanted to track compatibility with the spec, your pad functions need:

  1. Multi-character pad support.
  2. Don\'t truncate the input string
  3. Pad defaults to space

From my polyfill library, but apply your own due diligence for prototype extensions.

// Tests
\'hello\'.lpad(4) === \'hello\'
\'hello\'.rpad(4) === \'hello\'
\'hello\'.lpad(10) === \'     hello\'
\'hello\'.rpad(10) === \'hello     \'
\'hello\'.lpad(10, \'1234\') === \'41234hello\'
\'hello\'.rpad(10, \'1234\') === \'hello12341\'

String.prototype.lpad || (String.prototype.lpad = function( length, pad )
{
    if( length < this.length ) return this;

    pad = pad || \' \';
    let str = this;

    while( str.length < length )
    {
        str = pad + str;
    }

    return str.substr( -length );
});

String.prototype.rpad || (String.prototype.rpad = function( length, pad )
{
    if( length < this.length ) return this;

    pad = pad || \' \';
    let str = this;

    while( str.length < length )
    {
        str += pad;
    }

    return str.substr( 0, length );
});


回答16:

Here is a simple answer in basically one line of code.

var value = 35 // the numerical value
var x = 5 // the minimum length of the string

var padded = (\"00000\" + value).substr(-x);

Make sure the number of characters in you padding, zeros here, is at least as many as your intended minimum length. So really, to put it into one line, to get a result of \"00035\" in this case is:

var padded = (\"00000\" + 35).substr(-5);


回答17:

padding string has been inplemented in new javascript version.

str.padStart(targetLength [, padString])

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/String/padStart

If you want your own function check this example:

const myString = \'Welcome to my house\';
String.prototype.padLeft = function(times = 0, str = \' \') {
    return (Array(times).join(str) + this);
}
console.log(myString.padLeft(12, \':\'));
//:::::::::::Welcome to my house


回答18:

Array manipulations are really slow compared to simple string concat. Of course, benchmark for your use case.

function(string, length, pad_char, append) {
    string = string.toString();
    length = parseInt(length) || 1;
    pad_char = pad_char || \' \';

    while (string.length < length) {
        string = append ? string+pad_char : pad_char+string;
    }
    return string;
};


回答19:

A variant of @Daniel LaFavers\' answer.

var mask = function (background, foreground) {
  bg = (new String(background));
  fg = (new String(foreground));
  bgl = bg.length;
  fgl = fg.length;
  bgs = bg.substring(0, Math.max(0, bgl - fgl));
  fgs = fg.substring(Math.max(0, fgl - bgl));
  return bgs + fgs;
};

For example:

mask(\'00000\', 11  );   // \'00011\'
mask(\'00011\',\'00\' );   // \'00000\'
mask( 2     , 3   );   // \'3\'
mask(\'0\'    ,\'111\');   // \'1\'
mask(\'fork\' ,\'***\');   // \'f***\'
mask(\'_____\',\'dog\');   // \'__dog\'


回答20:

It\'s 2014, and I suggest a Javascript string-padding function. Ha!

Bare-bones: right-pad with spaces

function pad ( str, length ) {
    var padding = ( new Array( Math.max( length - str.length + 1, 0 ) ) ).join( \" \" );
    return str + padding;
}

Fancy: pad with options

/**
 * @param {*}       str                         input string, or any other type (will be converted to string)
 * @param {number}  length                      desired length to pad the string to
 * @param {Object}  [opts]
 * @param {string}  [opts.padWith=\" \"]          char to use for padding
 * @param {boolean} [opts.padLeft=false]        whether to pad on the left
 * @param {boolean} [opts.collapseEmpty=false]  whether to return an empty string if the input was empty
 * @returns {string}
 */
function pad ( str, length, opts ) {
    var padding = ( new Array( Math.max( length - ( str + \"\" ).length + 1, 0 ) ) ).join( opts && opts.padWith || \" \" ),
        collapse = opts && opts.collapseEmpty && !( str + \"\" ).length;
    return collapse ? \"\" : opts && opts.padLeft ? padding + str : str + padding;
}

Usage (fancy):

pad( \"123\", 5 );
// returns \"123  \"

pad( 123, 5 );
// returns \"123  \" - non-string input

pad( \"123\", 5, { padWith: \"0\", padLeft: true } );
// returns \"00123\"

pad( \"\", 5 );
// returns \"     \"

pad( \"\", 5, { collapseEmpty: true } );
// returns \"\"

pad( \"1234567\", 5 );
// returns \"1234567\"


回答21:

If you don\'t mind including a utility library, lodash library has _.pad, _.padLeft and _.padRight functions.



回答22:

I think its better to avoid recursion because its costly.

function padLeft(str,size,padwith) {
	if(size <= str.length) {
        // not padding is required.
		return str;
	} else {
        // 1- take array of size equal to number of padding char + 1. suppose if string is 55 and we want 00055 it means we have 3 padding char so array size should be 3 + 1 (+1 will explain below)
        // 2- now join this array with provided padding char (padwith) or default one (\'0\'). so it will produce \'000\'
        // 3- now append \'000\' with orginal string (str = 55), will produce 00055

        // why +1 in size of array? 
        // it is a trick, that we are joining an array of empty element with \'0\' (in our case)
        // if we want to join items with \'0\' then we should have at least 2 items in the array to get joined (array with single item doesn\'t need to get joined).
        // <item>0<item>0<item>0<item> to get 3 zero we need 4 (3+1) items in array   
		return Array(size-str.length+1).join(padwith||\'0\')+str
	}
}

alert(padLeft(\"59\",5) + \"\\n\" +
     padLeft(\"659\",5) + \"\\n\" +
     padLeft(\"5919\",5) + \"\\n\" +
     padLeft(\"59879\",5) + \"\\n\" +
     padLeft(\"5437899\",5));



回答23:

Here is a JavaScript function that adds specified number of paddings with custom symble. the function takes three parameters.

    padMe --> string or number to left pad
    pads  --> number of pads
    padSymble --> custom symble, default is \"0\" 

    function leftPad(padMe, pads, padSymble) {
         if( typeof padMe === \"undefined\") {
             padMe = \"\";
         }
         if (typeof pads === \"undefined\") {
             pads = 0;
         }
         if (typeof padSymble === \"undefined\") {
             padSymble = \"0\";
         }

         var symble = \"\";
         var result = [];
         for(var i=0; i < pads ; i++) {
            symble += padSymble;
         }
        var length = symble.length - padMe.toString().length;
        result = symble.substring(0, length);
        return result.concat(padMe.toString());
    }
/* Here are some results:

> leftPad(1)
\"1\"
> leftPad(1, 4)
\"0001\"
> leftPad(1, 4, \"0\")
\"0001\"
> leftPad(1, 4, \"@\")
\"@@@1\"

*/


回答24:

/**************************************************************************************************
Pad a string to pad_length fillig it with pad_char.
By default the function performs a left pad, unless pad_right is set to true.

If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place.
**************************************************************************************************/
if(!String.prototype.pad)
String.prototype.pad = function(pad_char, pad_length, pad_right) 
{
   var result = this;
   if( (typeof pad_char === \'string\') && (pad_char.length === 1) && (pad_length > this.length) )
   {
      var padding = new Array(pad_length - this.length + 1).join(pad_char); //thanks to http://stackoverflow.com/questions/202605/repeat-string-javascript/2433358#2433358
      result = (pad_right ? result + padding : padding + result);
   }
   return result;
}

And then you can do:

alert( \"3\".pad(\"0\", 3) ); //shows \"003\"
alert( \"hi\".pad(\" \", 3) ); //shows \" hi\"
alert( \"hi\".pad(\" \", 3, true) ); //shows \"hi \"


回答25:

If you just want a very simple hacky one-liner to pad, just make a string of the desired padding character of the desired max padding length and then substring it to the length of what you want to pad.

Example: padding the string store in e with spaces to 25 characters long.

var e = \"hello\"; e = e + \"                         \".substring(e.length)

Result: \"hello \"

If you want to do the same with a number as input just call .toString() on it before.



回答26:

A friend asked about using a JavaScript function to pad left. It turned into a little bit of an endeavor between some of us in chat to code golf it. This was the result:

function l(p,t,v){
    v+=\"\";return v.length>=t?v:l(p,t,p+v); 
}

It ensures that the value to be padded is a string, and then if it isn\'t the length of the total desired length it will pad it once and then recurse. Here is what it looks like with more logical naming and structure

function padLeft(pad, totalLength, value){
    value = value.toString();

    if( value.length >= totalLength ){
        return value;
    }else{
        return padLeft(pad, totalLength, pad + value);
    }
}

The example we were using was to ensure that numbers were padded with 0 to the left to make a max length of 6. Here is an example set:

function l(p,t,v){v+=\"\";return v.length>=t?v:l(p,t,p+v);}

var vals = [6451,123,466750];

var pad = l(0,6,vals[0]);// pad with 0\'s, max length 6

var pads = vals.map(function(i){ return l(0,6,i) });

document.write(pads.join(\"<br />\"));



回答27:

  1. Never insert data somewhere (especially not at beginning, like str = pad + str;), since the data will be reallocated everytime. Append always at end!
  2. Don\'t pad your string in the loop. Leave it alone and build your pad string first. In the end concatenate it with your main string.
  3. Don\'t assign padding string each time (like str += pad;). It is much faster to append the padding string to itself and extract first x-chars (the parser can do this efficiently if you extract from first char). This is exponential growth, which means that it wastes some memory temporarily (you should not do this with extremely huge texts).

if (!String.prototype.lpad) {
    String.prototype.lpad = function(pad, len) {
        while (pad.length < len) {
            pad += pad;
        }
        return pad.substr(0, len-this.length) + this;
    }
}

if (!String.prototype.rpad) {
    String.prototype.rpad = function(pad, len) {
        while (pad.length < len) {
            pad += pad;
        }
        return this + pad.substr(0, len-this.length);
    }
}



回答28:

Here\'s my take

I\'m not so sure about it\'s performance, but I find it much more readable than other options I saw around here...

var replicate = function(len, char) {
  return Array(len+1).join(char || \' \');
};

var padr = function(text, len, char) {
  if (text.length >= len) return text;
  return text + replicate(len-text.length, char);
};


回答29:

1. function
var _padLeft = function(paddingString, width, replacementChar) {
    return paddingString.length >= width ? paddingString : _padLeft(replacementChar + paddingString, width, replacementChar || \' \');
};

2. String prototype
String.prototype.padLeft = function(width, replacementChar) {
        return this.length >= width ? this.toString() : (replacementChar + this).padLeft(width, replacementChar || \' \');
};

3. slice
(\'00000\' + paddingString).slice(-5)


回答30:

Based on the best answers of this question I have made a prototype for String called padLeft (exactly like we have in C#):

String.prototype.padLeft = function (paddingChar, totalWidth) {
    if (this.toString().length >= totalWidth)
        return this.toString();

    var array = new Array(totalWidth); 

    for (i = 0; i < array.length; i++)
        array[i] = paddingChar;

    return (array.join(\"\") + this.toString()).slice(-array.length);
}

Usage:

var str = \"12345\";
console.log(str.padLeft(\"0\", 10)); //Result is: \"0000012345\"

JsFiddle