【问题标题】: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 个。
  • 今天可能推荐placeholder。将此应用于所有具有maxlength<input>s 看起来像document.querySelectorAll("[maxlength]").forEach((element) => element.placeholder = "#".repeat(element.maxLength));

标签: javascript html string


【解决方案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;
}

更多信息:

【讨论】:

  • 这仍然比我的解决方案慢得多(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);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-09-27
          • 1970-01-01
          • 2011-08-25
          • 1970-01-01
          • 2021-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多