What is the best or most concise method for returning a string repeated an arbitrary amount of times?
The following is my best shot so far:
function
Concatenating strings based on an number.
function concatStr(str, num) {
var arr = [];
//Construct an array
for (var i = 0; i < num; i++)
arr[i] = str;
//Join all elements
str = arr.join('');
return str;
}
console.log(concatStr("abc", 3));
Hope that helps!
Recursive solution using divide and conquer:
function repeat(n, s) {
if (n==0) return '';
if (n==1 || isNaN(n)) return s;
with(Math) { return repeat(floor(n/2), s)+repeat(ceil(n/2), s); }
}
Good news! String.prototype.repeat is now a part of JavaScript.
"yo".repeat(2);
// returns: "yoyo"
The method is supported by all major browsers, except Internet Explorer and Android Webview. For an up to date list, see MDN: String.prototype.repeat > Browser compatibility.
MDN has a polyfill for browsers without support.
Expanding P.Bailey's solution:
String.prototype.repeat = function(num) {
return new Array(isNaN(num)? 1 : ++num).join(this);
}
This way you should be safe from unexpected argument types:
var foo = 'bar';
alert(foo.repeat(3)); // Will work, "barbarbar"
alert(foo.repeat('3')); // Same as above
alert(foo.repeat(true)); // Same as foo.repeat(1)
alert(foo.repeat(0)); // This and all the following return an empty
alert(foo.repeat(false)); // string while not causing an exception
alert(foo.repeat(null));
alert(foo.repeat(undefined));
alert(foo.repeat({})); // Object
alert(foo.repeat(function () {})); // Function
EDIT: Credits to jerone for his elegant ++num
idea!
I came here randomly and never had a reason to repeat a char in javascript before.
I was impressed by artistoex's way of doing it and disfated's results. I noticed that the last string concat was unnecessary, as Dennis also pointed out.
I noticed a few more things when playing with the sampling disfated put together.
The results varied a fair amount often favoring the last run and similar algorithms would often jockey for position. One of the things I changed was instead of using the JSLitmus generated count as the seed for the calls; as count was generated different for the various methods, I put in an index. This made the thing much more reliable. I then looked at ensuring that varying sized strings were passed to the functions. This prevented some of the variations I saw, where some algorithms did better at the single chars or smaller strings. However the top 3 methods all did well regardless of the string size.
Forked test set
http://jsfiddle.net/schmide/fCqp3/134/
// repeated string
var string = '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
// count paremeter is changed on every test iteration, limit it's maximum value here
var maxCount = 200;
var n = 0;
$.each(tests, function (name) {
var fn = tests[name];
JSLitmus.test(++n + '. ' + name, function (count) {
var index = 0;
while (count--) {
fn.call(string.slice(0, index % string.length), index % maxCount);
index++;
}
});
if (fn.call('>', 10).length !== 10) $('body').prepend('<h1>Error in "' + name + '"</h1>');
});
JSLitmus.runAll();
I then included Dennis' fix and decided to see if I could find a way to eek out a bit more.
Since javascript can't really optimize things, the best way to improve performance is to manually avoid things. If I took the first 4 trivial results out of the loop, I could avoid 2-4 string stores and write the final store directly to the result.
// final: growing pattern + prototypejs check (count < 1)
'final avoid': function (count) {
if (!count) return '';
if (count == 1) return this.valueOf();
var pattern = this.valueOf();
if (count == 2) return pattern + pattern;
if (count == 3) return pattern + pattern + pattern;
var result;
if (count & 1) result = pattern;
else result = '';
count >>= 1;
do {
pattern += pattern;
if (count & 1) result += pattern;
count >>= 1;
} while (count > 1);
return result + pattern + pattern;
}
This resulted in a 1-2% improvement on average over Dennis' fix. However, different runs and different browsers would show a fair enough variance that this extra code probably isn't worth the effort over the 2 previous algorithms.
A chart
Edit: I did this mostly under chrome. Firefox and IE will often favor Dennis by a couple %.
/**
@desc: repeat string
@param: n - times
@param: d - delimiter
*/
String.prototype.repeat = function (n, d) {
return --n ? this + (d || '') + this.repeat(n, d) : '' + this
};
this is how to repeat string several times using delimeter.