创建一个长度可变的字符串,用重复的字符填充


164

因此,我的问题已被其他人以下面的Java形式提出:Java-创建一个具有指定长度并填充有特定字符的新String实例。最佳解决方案?

。。。但我正在寻找其JavaScript等效项。

基本上,我想根据每个字段的“ maxlength”属性以“#”字符动态填充文本字段。因此,如果输入具有has maxlength="3",则该字段将用“ ###”填充。

理想情况下,会有类似Java的东西StringUtils.repeat("#", 10);,但是到目前为止,我能想到的最佳选择是一次遍历并附加“#”字符,直到达到最大长度为止。我不禁感到有比这更有效的方法了。

有任何想法吗?

仅供参考-我不能简单地在输入中设置默认值,因为“#”字符需要清晰显示,并且,如果用户未输入值,则需要在模糊时“重新填充”。这是我关注的“补充”步骤


1
您是否要屏蔽输入字段的文本?
Feisty Mango

@MatthewCox:不,要提供maxlength的可视显示。在这种情况下,它是针对一组电话号码字段,这些字段被分为号码的3个部分。这将显示,今年前2场需要3个数字,最后需要4
talemyn

Answers:


302

最好的方法(我已经看到)是

var str = new Array(len + 1).join( character );

这将创建具有给定长度的数组,然后将其与给定的字符串连接以重复。.join()不管元素是否分配了值,该函数都会遵守数组长度,并且未定义的值将呈现为空字符串。

您必须在所需的长度上加1,因为分隔符字符串位于数组元素之间


搞定了。:)我只需要记住parseInt()在输入maxlength值之前使用它来调整数组大小。正是我想要的。。。谢谢!
talemyn

11
注意,此解决方案非常慢。它看起来很性感,但可能完全是错误的方式。
霍根2015年

23
repeatString.prototype中内置的新函数现在可以处理此问题(ES6 +)
AlexMA

生病的解决方案。谢谢你!
C4d

156

尝试一下:P

s = '#'.repeat(10)

document.body.innerHTML = s


4
由于它是ECMAScript 6的一部分,因此绝对是最简单的实现,但也受到最少的支持。目前看来,它仅在Firefox,Chrome和桌面版Safari中受支持。
talemyn

5
如果您不介意使用lodash,则可以使用以下代码: _.repeat('*',10);
Geraud Gratacap

4
现在是2018年,ES6的地位已经确立-这应该是公认的答案。如果需要为不使用Babel或类似工具的用户支持旧版浏览器,则可以使用上述的lodash或使用polyfill进行备份。
seanTcoyote

@seanTcoyote尽我所愿,仍然有些人必须与IE 11和Adroid的Webview竞争,但都不支持该repeat()方法。期待有一天我不再需要关心它们了。。。
talemyn

不幸的是,与IE不兼容
Lorenzo Lerate

30

不幸的是,尽管这里提到的Array.join方法很简洁,但是它比基于字符串连接的实现慢了大约10倍。它在大字符串上的表现特别差。有关完整的性能详细信息,请参见下文。

在Firefox,Chrome,Node.js MacOS,Node.js Ubuntu和Safari上,我测试的最快实现是:

function repeatChar(count, ch) {
    if (count == 0) {
        return "";
    }
    var count2 = count / 2;
    var result = ch;

    // double the input until it is long enough.
    while (result.length <= count2) {
        result += result;
    }
    // use substring to hit the precise length target without
    // using extra memory
    return result + result.substring(0, count - result.length);
};

这很冗长,因此,如果要简洁的实现,可以采用幼稚的方法。它仍然比Array.join方法的性能好2倍至10倍,并且比小输入的两倍实现快。码:

// naive approach: simply add the letters one by one
function repeatChar(count, ch) {
    var txt = "";
    for (var i = 0; i < count; i++) {
        txt += ch;
    }
    return txt;
}

更多信息:


1
这仍然比我的解决方案慢得多(降低了2到3个数量级)。
霍根2015年

@Hogan您的解决方案不会从无处创建填充字符串。您可以自己创建它,然后仅提取一个子字符串。
StanE

对于超大字符串,此方法比Node.js中的Array.join慢10倍。
Anshul Koka

21

我会创建一个常量字符串,然后在其上调用子字符串。

就像是

var hashStore = '########################################';

var Fiveup = hashStore.substring(0,5);

var Tenup = hashStore.substring(0,10);

也快一点。

http://jsperf.com/const-vs-join


1
这非常聪明!它甚至可以用于包含多个字符的字符串模式。
马库斯

1
只需重新访问该页面,因为它似乎一直吸引了很多关注,并想对您的解决方案发表评论。尽管我绝对喜欢您的方法的简单性和速度,但我最大的担忧是维护/重用。在我的特定情况下,作为通用函数,我不需要超过4个字符,但使用固定长度的字符串意味着,如果用例需要更多的字符,则必须返回并更新字符串。其他两种解决方案在这方面具有更大的灵活性。速度为+1。
talemyn 2015年

1
哦,而且,另一方面(我意识到这确实是一种风格问题,而不是编程方面的问题),保持30个以上只能用于3-4个字符的字符串,效果并不理想我也是 。。。同样,围绕各种用例的解决方案灵活性存在一个小问题。
talemyn 2015年

@talemyn在IT中,一切都需要权衡。拥有4个字符串并使其变大,或者拥有30个字符串,不用担心。总而言之,任何大小的常量字符串(甚至1k)在现代计算机上的资源占用很少。
霍根2015年

@Hogan-完全同意。。。而且,这实际上就是我也不十分强调速度的部分原因。在我的特定用例中,我正在寻找三个长度分别为3、3和4个字符的字符串。虽然Pointy的解决方案最慢,但由于字符串较短且只有少数几个字符串,所以我选择了他,因为我喜欢它简化,易于阅读且易于维护的事实。最后,它们都是解决不同问题的好方法。。。这取决于您的具体情况的优先级。
talemyn 2015年


5

ES6的一个不错的选择是将padStart字符串设为空。像这样:

var str = ''.padStart(10, "#");

注意:这在IE(没有polyfill)中将不起作用。


3
有什么特别的理由建议您将s = '#'.repeat(10)@ 6的@ user4227915的答案推荐给其他()这种ES6方法?
talemyn

@talemyn更简单的语法
Mendy

3

适用于所有浏览器的版本

此功能可以满足您的要求,并且比接受的答案中建议的选项执行速度快得多:

var repeat = function(str, count) {
    var array = [];
    for(var i = 0; i <= count;)
        array[i++] = str;
    return array.join('');
}

您可以这样使用它:

var repeatedCharacter = repeat("a", 10);

要将此功能的性能与已接受答案中建议的选项的性能进行比较,请参阅此Fiddle此Fiddle以获得基准。

仅适用于现代浏览器的版本

在现代浏览器中,您现在还可以执行以下操作:

var repeatedCharacter = "a".repeat(10) };

此选项甚至更快。但是,不幸的是,它不适用于任何版本的Internet Explorer。

表格中的数字指定了完全支持该方法的第一个浏览器版本:

在此处输入图片说明


3
For Evergreen browsers, this will build a staircase based on an incoming character and the number of stairs to build.
function StairCase(character, input) {
    let i = 0;
    while (i < input) {
        const spaces = " ".repeat(input - (i+1));
        const hashes = character.repeat(i + 1);
        console.log(spaces + hashes);
        i++;
    }
}

//Implement
//Refresh the console
console.clear();
StairCase("#",6);   

您还可以为较旧的浏览器添加重复填充

    if (!String.prototype.repeat) {
      String.prototype.repeat = function(count) {
        'use strict';
        if (this == null) {
          throw new TypeError('can\'t convert ' + this + ' to object');
        }
        var str = '' + this;
        count = +count;
        if (count != count) {
          count = 0;
        }
        if (count < 0) {
          throw new RangeError('repeat count must be non-negative');
        }
        if (count == Infinity) {
          throw new RangeError('repeat count must be less than infinity');
        }
        count = Math.floor(count);
        if (str.length == 0 || count == 0) {
          return '';
        }
        // Ensuring count is a 31-bit integer allows us to heavily optimize the
        // main part. But anyway, most current (August 2014) browsers can't handle
        // strings 1 << 28 chars or longer, so:
        if (str.length * count >= 1 << 28) {
          throw new RangeError('repeat count must not overflow maximum string size');
        }
        var rpt = '';
        for (;;) {
          if ((count & 1) == 1) {
            rpt += str;
          }
          count >>>= 1;
          if (count == 0) {
            break;
          }
          str += str;
        }
        // Could we try:
        // return Array(count + 1).join(this);
        return rpt;
      }
    } 

2

基于来自Hogan和Zero Trick Pony的答案。我认为这应该既快速又灵活,足以处理大多数用例:

var hash = '####################################################################'

function build_string(length) {  
    if (length == 0) {  
        return ''  
    } else if (hash.length <= length) {  
        return hash.substring(0, length)  
    } else {  
        var result = hash  
        const half_length = length / 2  
        while (result.length <= half_length) {  
            result += result  
        }  
        return result + result.substring(0, length - result.length)  
    }  
}  

请为您的答案添加更多说明,因为代码段本身无法提供答案。
Clijsters

@Leandro Clever并最大程度地减少了处理!+1
LMSingh '17

我认为您的意思是hash.length> = length
cipak

1

如果愿意,可以将函数的第一行用作单行:

function repeat(str, len) {
    while (str.length < len) str += str.substr(0, len-str.length);
    return str;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.