web-dev-qa-db-fra.com

Créer une chaîne de longueur variable, remplie d'un caractère répété

Donc, ma question a été posée par quelqu'un d'autre sous sa forme Java ici: Java - Créer une nouvelle instance String avec une longueur spécifiée et renseignée avec un caractère spécifique. Meilleure solution?

. . . mais je cherche son équivalent JavaScript.

En gros, je souhaite remplir dynamiquement les champs de texte avec des caractères "#", en fonction de l'attribut "maxlength" de chaque champ. Donc, si une entrée a maxlength="3", alors le champ sera rempli avec "###".

Idéalement, il devrait y avoir quelque chose comme Java StringUtils.repeat("#", 10);, mais pour l’instant, la meilleure option à laquelle je puisse penser est de passer en boucle et d’ajouter les caractères "#", un à la fois, jusqu’à atteindre la longueur maximale. Je ne peux m'empêcher de penser qu'il existe un moyen plus efficace de le faire.

Des idées?

FYI - Je ne peux pas simplement définir une valeur par défaut dans la saisie, car les caractères "#" doivent être effacés lors de la mise au point et, si l'utilisateur n'a pas saisi de valeur, il doit être "rempli" le flou. C'est l'étape de "remplissage" qui me concerne

129
talemyn

La meilleure façon de faire ceci (que j'ai vu) est 

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

Cela crée un tableau avec la longueur donnée, puis le joint avec la chaîne donnée à répéter. La fonction .join() respecte la longueur du tableau, que les éléments soient affectés d'une valeur ou non, et les valeurs non définies sont restituées sous forme de chaînes vides.

Vous devez ajouter 1 à la longueur souhaitée car la chaîne de séparation va entre les éléments du tableau.

261
Pointy

Essayez ceci: P

s = '#'.repeat(10)

document.body.innerHTML = s

106
user4227915

Malheureusement, bien que l'approche Array.join mentionnée ici soit concise, elle est environ 10 fois plus lente qu'une implémentation basée sur la concaténation de chaînes. Il fonctionne particulièrement mal sur les grosses cordes. Voir ci-dessous pour plus de détails sur les performances.

Sur Firefox, Chrome, Node.js MacOS, Node.js Ubuntu et Safari, la mise en oeuvre la plus rapide que j'ai testée était:

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);
};

C'est verbeux, donc si vous voulez une mise en œuvre laconique, vous pouvez utiliser l'approche naïve; il fonctionne toujours entre 2X et 10X mieux que l’approche Array.join, et est également plus rapide que l’implémentation doublée pour les petits intrants. Code:

// 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;
}

Informations complémentaires:

28
Zero Trick Pony

Je créerais une chaîne constante, puis j'appellerais une sous-chaîne dessus.

Quelque chose comme 

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

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

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

Un peu plus vite aussi.

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

20
Hogan

Version qui fonctionne dans tous les navigateurs

Cette fonction fait ce que vous voulez et fonctionne beaucoup plus rapidement que l'option suggérée dans la réponse acceptée:

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

Vous l'utilisez comme ceci:

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

Pour comparer les performances de cette fonction avec celles de l'option proposée dans la réponse acceptée, voir this Fiddle et this Fiddle pour les points de repère. .

Version pour les navigateurs modernes uniquement

Dans les navigateurs modernes, vous pouvez maintenant aussi faire ceci:

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

Cette option est encore plus rapide. Cependant, malheureusement, cela ne fonctionne dans aucune version d'Internet Explorer. 

Les nombres dans la table spécifient la première version du navigateur qui supporte pleinement la méthode:

 enter image description here

3
John Slegers
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);   

Vous pouvez également ajouter un polyfill à répéter pour les anciens navigateurs

    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;
      }
    } 
3
Terry Slack

Basé sur les réponses de Hogan et Zero Trick Pony. Je pense que cela devrait être à la fois rapide et flexible pour pouvoir gérer la plupart des cas d'utilisation 

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)  
    }  
}  
2
Leandro

Une excellente option ES6 serait de padStart une chaîne vide. Comme ça:

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

Remarque: cela ne fonctionnera pas dans IE (sans polyfill).

1
Mendy

Vous pouvez utiliser la première ligne de la fonction comme une ligne si vous aimez:

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