返回任意次数的字符串的最佳或最简洁的方法是什么?
以下是我目前为止拍得最好的照片:
function repeat(s, n){
var a = [];
while(a.length < n){
a.push(s);
}
return a.join('');
}
返回任意次数的字符串的最佳或最简洁的方法是什么?
以下是我目前为止拍得最好的照片:
function repeat(s, n){
var a = [];
while(a.length < n){
a.push(s);
}
return a.join('');
}
当前回答
我随机来到这里,从来没有理由在javascript中重复字符。
我对artistoex的做法印象深刻,对结果感到失望。我注意到最后一个串连接是不必要的,正如丹尼斯也指出的那样。
我注意到一些更多的东西,当玩抽样disfate放在一起。
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.
分叉测试集
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();
然后我加入了丹尼斯的解决方案,并决定看看我是否能找到更多的方法。
由于javascript不能真正优化,提高性能的最好方法是手动避免一些东西。如果我把前4个琐碎的结果从循环中取出,我可以避免2-4个字符串存储,并将最后的存储直接写入结果。
// 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;
}
这比丹尼斯的修复方案平均提高了1-2%。然而,不同的运行和不同的浏览器会显示相当大的差异,这额外的代码可能不值得在前面的两种算法上付出努力。
一个图表
编辑:我这样做主要是在chrome浏览器。Firefox和IE通常对Dennis的偏爱程度为百分之几。
其他回答
这可能是最小的递归:-
String.prototype.repeat = function(n,s) {
s = s || ""
if(n>0) {
s += this
s = this.repeat(--n,s)
}
return s}
使用分治法的递归解:
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); }
}
String.prototype.repeat现在是ES6标准。
'abc'.repeat(3); //abcabcabc
人们将这一问题过于复杂,甚至浪费了表现。数组?递归?你在跟我开玩笑吧。
function repeat (string, times) {
var result = ''
while (times-- > 0) result += string
return result
}
编辑。我做了一些简单的测试,与artistoex / disfated和其他一些人发布的按位版本进行比较。后者只是稍微快一点,但内存效率高了几个数量级。对于单词'blah'的1000000次重复,使用简单的串联算法(上面),Node进程的容量达到46兆字节,而使用对数算法只有5.5兆字节。后者绝对是正确的选择。为了清晰起见,我将其转发:
function repeat (string, times) {
var result = ''
while (times > 0) {
if (times & 1) result += string
times >>= 1
string += string
}
return result
}
首先,OP的问题似乎是关于简明性的——我理解的意思是“简单易读”,而大多数答案似乎是关于效率的——这显然不是一回事,而且我认为,除非你实现了一些非常具体的大型数据操作算法,否则当你实现基本的数据操作Javascript函数时,不应该担心。简洁更重要。
其次,正如André Laszlo所指出的,字符串。repeat是ECMAScript 6的一部分,并且已经在几个流行的实现中可用——因此是String最简洁的实现。重复是不执行的;-)
最后,如果您需要支持不提供ECMAScript 6实现的主机,André Laszlo提到的MDN的polyfill一点也不简洁。
所以,废话不多说——下面是我简洁的填充:
String.prototype.repeat = String.prototype.repeat || function(n){
return n<=1 ? this : this.concat(this.repeat(n-1));
}
是的,这是递归。我喜欢递归——它们很简单,如果操作正确,很容易理解。关于效率,如果语言支持它,如果写得正确,它们可以非常高效。
从我的测试来看,这种方法比Array快60%。加入的方法。虽然它显然与disfate的实现相去甚远,但它比两者都要简单得多。
我的测试设置是节点v0.10,使用“严格模式”(我认为它支持某种TCO),对一个10个字符的字符串调用repeat(1000)一百万次。