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

Posted

技术标签:

【中文标题】创建一个可变长度的字符串,填充一个重复的字符【英文标题】:Create a string of variable length, filled with a repeated character 【发布时间】:2012-12-29 21:53:32 【问题描述】:

所以,我的问题已被其他人以 Java 形式在这里提出:Java - Create a new String instance with specified length and filled with specific character. Best solution?

。 . .但我正在寻找它的 javascript 等价物。

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

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

有什么想法吗?

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

【问题讨论】:

您这样做是为了掩盖输入字段的文本吗? @MatthewCox:不,更多的是提供最大长度的可视化显示。在这种情况下,它用于一组电话号码字段,这些字段分为号码的 3 个部分。它会显示前 2 个字段需要 3 个数字,最后一个需要 4 个。 Repeat String - Javascript的可能重复 今天可能推荐placeholder。将此应用于所有具有maxlength<input>s 看起来像document.querySelectorAll("[maxlength]").forEach((element) => element.placeholder = "#".repeat(element.maxLength)); 【参考方案1】:

最好的方法(我见过)是

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

这将创建一个具有给定长度的数组,然后将它与给定的字符串连接以重复。 .join() 函数尊重数组长度,无论元素是否分配了值,并且未定义的值呈现为空字符串。

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

【讨论】:

成功了。 :) 我只需要记住在输入 maxlength 值上使用parseInt(),然后再使用它来调整数组的大小。正是我想要的。 . .谢谢! 注意,这个解决方案非常慢。它看起来很性感,但可能是完全错误的做法。 String.prototype 中内置的新 repeat 函数现在可以处理这个问题(ES6+) 病态解决方案。谢谢!【参考方案2】:

试试看:P

s = '#'.repeat(10)

document.body.innerhtml = s

【讨论】:

绝对是最简单的实现,但也是受支持最少的,因为它是 ECMAScript 6 的一部分。目前看来,它仅在 Firefox、Chrome 和桌面版 Safari 中受支持。 如果你不介意使用lodash,你可以使用下面的:_.repeat('*',10); 现在是 2018 年,ES6 已经成熟——这应该是公认的答案。如果需要为那些不使用 Babel 或类似工具的人支持旧版浏览器,您可以使用上面提到的 lodash,或者使用 polyfill 进行备份。 @seanTcoyote 尽管我很想,仍然有人不得不与 IE 11 和 Adroid 的 Webviews 抗衡,它们都不支持 repeat() 方法。期待有一天,我自己不用再关心他们了。 . . 很遗憾,不兼容IE【参考方案3】:

ES2015 最简单的方法是做类似

'X'.repeat(data.length)

X 是任意字符串,data.length 是所需长度。

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

【讨论】:

今天阅读本文的任何人的最佳答案。【参考方案4】:

不幸的是,虽然这里提到的 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;

更多信息:

Run speed test in your own browser Full source code of speed test Speed test results

【讨论】:

这仍然比我的解决方案慢得多(2 到 3 个数量级)。 @Hogan 您的解决方案不会从任何地方创建填充字符串。您自己创建它,然后提取一个子字符串。 对于非常大的字符串,这种方法比 Node.js 中的 Array.join 慢 10 倍。【参考方案5】:

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

有点像

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

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

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

也快一点。

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

【讨论】:

这很聪明!它甚至适用于包含多个字符的字符串模式。 刚刚重新访问此页面,因为它似乎一直受到很多关注并想对您的解决方案发表评论。虽然我绝对喜欢您的方法的简单性和速度,但我最关心的是维护/重用。虽然在我的特定场景中,我不需要超过 4 个字符,但作为一个通用函数,使用固定长度的字符串意味着如果您的用例需要更多字符,您必须返回并更新字符串。其他两种解决方案在这方面提供了更大的灵活性。不过,为速度 +1。 哦,另一方面(我意识到这实际上更多是一种风格问题,而不是程序化问题),维护一个 30 多个字符的字符串,该字符串只能用于 3- 4 个角色也不适合我。 . .再次,关于各种用例的解决方案灵活性的小问题。 @talemyn 在 IT 中,一切都是权衡。有一个 4 个字符的字符串,让它变大或有一个 30 个字符的字符串,不用担心。总而言之,任何大小的常量字符串——即使是 1k,在现代机器上都是很小的资源使用。 @Hogan - 完全同意。 . .而且,这实际上也是我没有特别强调速度的部分原因。在我的特定用例中,我正在寻找三个长度分别为 3、3 和 4 个字符的字符串。虽然 Pointy 的解决方案是最慢的,因为字符串很短而且只有几个,我选择了他的,因为我喜欢它流线型、易于阅读和易于维护的事实。最后,对于问题的不同变体,它们都是很好的解决方案。 . .这一切都取决于您的具体情况的优先事项。【参考方案6】:

一个很好的 ES6 选项是 padStart 一个空字符串。像这样:

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

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

【讨论】:

是否有任何理由特别推荐这种 ES6 方法而不是 @user4227915 上面的答案中的另一种方法 (s = '#'.repeat(10))? 仅供参考,padStart 和重复功能给出不同的结果。 太棒了,我不知道我们有这个原生方法! @MichaelHarley 怎么样? '#'.repeat(10)===''.padStart(10, "#"); @EricLaw repeatpadStart 有不同的用例。对于空字符串?它'有点'一样。使用需要精确长度的字符串的动态字符串?你肯定需要padStartpadEnd 而不是repeat,你可以用额外的逻辑重现相同的结果。【参考方案7】:

适用于所有浏览器的版本

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

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

你这样使用它:

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

要将此函数的性能与已接受答案中提出的选项的性能进行比较,请参阅 this Fiddlethis Fiddle 以获取基准。

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

在现代浏览器中,您现在也可以这样做:

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

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

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

【讨论】:

在我的浏览器 (Vivaldi 2.6.1566.49 (Stable channel) (64-bit)) 中,您的解决方案所需的时间大约是接受答案的两倍。 @markuss :当我今天在最新的 Chrome 中运行基准测试时,这对我来说大致相同。请注意,我的答案已经超过 4 年了,所以性能差异可能是这 4 年中发生的更新的结果......【参考方案8】:
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);   

You can also add a polyfill for Repeat for older browsers

    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;
      
     

【讨论】:

【参考方案9】:

基于 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)  
      
  

【讨论】:

请为您的答案添加更多解释,因为代码 sn-p 本身不提供答案。 @Leandro 聪明并最大限度地减少处理! +1 我认为你的意思是 hash.length >= length【参考方案10】:

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

function repeat(str, len) 
    while (str.length < len) str += str.substr(0, len-str.length);
    return str;

【讨论】:

【参考方案11】:

我愿意

Buffer.alloc(length, character).toString()

【讨论】:

【参考方案12】:

如果您需要的是性能(在 ES6 之前),那么 substr 和模板字符串的组合可能是最好的。这个函数是我用来创建空格填充字符串的,但你可以将模板更改为你需要的任何内容:

function strRepeat(intLen, strTemplate) 
  strTemplate = strTemplate || "          ";
  var strTxt = '';
  while(intLen > strTemplate.length) 
    strTxt += strTemplate;
    intLen -= strTemplate.length;
  
  return ((intLen > 0) ? strTxt + strTemplate.substr(0, intLen) : strTxt);

【讨论】:

以上是关于创建一个可变长度的字符串,填充一个重复的字符的主要内容,如果未能解决你的问题,请参考以下文章

SQL记录-PLSQL字符串

ECMAScript6补全字符串长度方法padStart()和padEnd()

使用 std::fmt 格式化时,如何按可变数量填充数字?

找出一个可变长度的字符串?

为python中的参数化查询生成变量长度放置保持器字符串[重复]

CHAR 和 VARCHAR