Erstellen Sie eine Zeichenfolge mit variabler Länge, die mit einem wiederholten Zeichen gefüllt ist


164

Daher wurde meine Frage hier von einer anderen Person in Java-Form gestellt: Java - Erstellen Sie eine neue String-Instanz mit der angegebenen Länge und dem angegebenen Zeichen. Beste Lösung?

. . . aber ich suche nach seinem JavaScript-Äquivalent.

Grundsätzlich möchte ich Textfelder dynamisch mit "#" Zeichen füllen, basierend auf dem Attribut "maxlength" jedes Felds. Wenn also eine Eingabe vorhanden ist maxlength="3", wird das Feld mit "###" gefüllt.

Im Idealfall gibt es so etwas wie Java StringUtils.repeat("#", 10);, aber bisher ist die beste Option, die ich mir vorstellen kann, das Durchlaufen und Anhängen der "#" - Zeichen nacheinander, bis die maximale Länge erreicht ist. Ich kann das Gefühl nicht loswerden, dass es einen effizienteren Weg gibt, dies zu tun.

Irgendwelche Ideen?

Zu Ihrer Information - Ich kann nicht einfach einen Standardwert in der Eingabe festlegen, da die "#" Zeichen im Fokus gelöscht werden müssen und, wenn der Benutzer keinen Wert eingegeben hat, bei Unschärfe "nachgefüllt" werden müssen. Es ist der "Nachfüll" -Schritt, mit dem ich mich befasse


1
Tun Sie dies, um den Text eines Eingabefeldes zu maskieren?
Feisty Mango

@MatthewCox: Nein, es ist mehr, eine visuelle Anzeige der maximalen Länge bereitzustellen. In diesem Fall handelt es sich um eine Reihe von Telefonnummernfeldern, die in drei Teile der Nummer unterteilt sind. Es würde zeigen, dass die ersten 2 Felder 3 Ziffern und die letzten 4 benötigen.
Talemyn

mögliches Duplikat von Repeat String - Javascript
Felix Kling

Antworten:


301

Der beste Weg dies zu tun (den ich gesehen habe) ist

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

Dadurch wird ein Array mit der angegebenen Länge erstellt und anschließend mit der angegebenen Zeichenfolge verknüpft, um es zu wiederholen. Die .join()Funktion berücksichtigt die Array-Länge, unabhängig davon, ob den Elementen Werte zugewiesen wurden, und undefinierte Werte werden als leere Zeichenfolgen gerendert.

Sie müssen der gewünschten Länge 1 hinzufügen, da die Trennzeichenfolge zwischen den Array-Elementen liegt.


Geschafft. :) Ich musste nur daran denken, parseInt()den Wert für die maximale Länge der Eingänge zu verwenden, bevor ich ihn zur Größe des Arrays verwendete. Genau das, wonach ich gesucht habe. . . Vielen Dank!
Talemyn

11
Beachten Sie, dass diese Lösung SEHR langsam ist. Es sieht sexy aus, ist aber wahrscheinlich genau der falsche Weg, dies zu tun.
Hogan

23
Neue repeatFunktion in String.prototype integriert jetzt (ES6 +)
AlexMA

Kranke Lösung. Danke dafür!
C4d

155

Probieren Sie es aus: P.

s = '#'.repeat(10)

document.body.innerHTML = s


4
Auf jeden Fall die einfachste Implementierung, aber auch die am wenigsten unterstützte, da sie Teil von ECMAScript 6 ist. Sieht so aus, als würde sie derzeit nur in Firefox, Chrome und der Desktop-Version von Safari unterstützt.
Talemyn

5
Wenn es Ihnen nichts ausmacht, lodash zu verwenden , können Sie Folgendes verwenden: _.repeat('*',10);
Geraud Gratacap

4
Es ist jetzt 2018 und ES6 ist gut etabliert - dies sollte die akzeptierte Antwort sein. Und falls Sie ältere Browser für diejenigen unterstützen müssen, die Babel oder ähnliches nicht verwenden, können Sie lodash wie oben erwähnt oder eine Polyfüllung für die Sicherung verwenden.
SeanTcoyote

@seanTcoyote So sehr ich möchte, gibt es immer noch Leute, die sich mit IE 11 und Adroid's Webviews auseinandersetzen müssen, von denen keiner die repeat()Methode unterstützt. Ich freue mich auf den Tag, an dem ich mich nicht mehr um sie kümmern muss. . .
Talemyn

Leider nicht kompatibel mit IE
Lorenzo Lerate

30

Obwohl der hier erwähnte Array.join-Ansatz knapp ist, ist er leider etwa 10-mal langsamer als eine auf String-Verkettung basierende Implementierung. Es funktioniert besonders schlecht bei großen Saiten. Siehe unten für vollständige Leistungsdetails.

Unter Firefox, Chrome, Node.js MacOS, Node.js Ubuntu und Safari war die schnellste Implementierung, die ich getestet habe:

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

Dies ist ausführlich. Wenn Sie also eine knappe Implementierung wünschen, können Sie sich für den naiven Ansatz entscheiden. Es bietet immer noch eine 2- bis 10-fache Leistung zwischen dem Array.join-Ansatz und ist außerdem schneller als die Verdopplungsimplementierung für kleine Eingaben. 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;
}

Weitere Informationen:


1
Dies ist immer noch viel langsamer (um 2 bis 3 Größenordnungen) als meine Lösung.
Hogan

@Hogan Ihre Lösung erstellt keine gefüllte Zeichenfolge aus dem Nichts. Sie erstellen es selbst und extrahieren dann einfach einen Teilstring.
StanE

Dieser Ansatz ist 10x langsamer als Array.join in Node.js für extrem große Zeichenfolgen.
Anshul Koka

21

Ich würde eine konstante Zeichenfolge erstellen und dann Teilzeichenfolge darauf aufrufen.

Etwas wie

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

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

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

Ein bisschen schneller auch.

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


1
Das ist sehr klug! Und es funktioniert sogar mit Zeichenfolgenmustern, die mehrere Zeichen enthalten.
Markus

1
Ich habe diese Seite nur noch einmal besucht, weil sie anscheinend immer mehr Aufmerksamkeit erhält und Ihre Lösung kommentieren wollte. Während ich die Einfachheit und Geschwindigkeit Ihres Ansatzes definitiv mag, war meine größte Sorge dabei die Wartung / Wiederverwendung. Während ich in meinem speziellen Szenario nicht mehr als 4 Zeichen benötigte, bedeutet die Verwendung einer Zeichenfolge mit fester Länge als generische Funktion, dass Sie zurückkommen und die Zeichenfolge aktualisieren müssen, wenn Ihr Anwendungsfall jemals mehr Zeichen benötigt. Die beiden anderen Lösungen ermöglichen diesbezüglich mehr Flexibilität. +1 für die Geschwindigkeit.
Talemyn

1
Oh, und auf der anderen Seite (und mir ist klar, dass dies eher ein stilistisches als ein programmatisches Problem ist), war es nicht gut, eine Zeichenfolge von mehr als 30 Zeichen beizubehalten, die immer nur für 3-4 Zeichen verwendet wird ich auch . . . Auch hier ein kleines Problem in Bezug auf die Flexibilität der Lösung für verschiedene Anwendungsfälle.
Talemyn

@talemyn In der IT ist alles ein Kompromiss. Haben Sie eine 4-stellige Zeichenfolge und vergrößern Sie sie oder haben Sie eine 30-stellige Zeichenfolge und machen Sie sich keine Sorgen. Alles in allem ist eine konstante Zeichenfolge jeder Größe - sogar 1 KB - ein winziger Ressourcenverbrauch auf modernen Maschinen.
Hogan

@ Hogan - stimme vollkommen zu. . . und das ist eigentlich ein Teil des Grundes, warum ich auch nicht viel Wert auf die Geschwindigkeit gelegt habe. In meinem speziellen Anwendungsfall suchte ich nach drei Zeichenfolgen mit einer Länge von 3, 3 und 4 Zeichen. Während Pointys Lösung am langsamsten war, da die Saiten kurz waren und es nur wenige gab, entschied ich mich für seine, weil mir die Tatsache gefiel, dass sie rationalisiert, leicht zu lesen und leicht zu warten war. Am Ende sind sie alle gute Lösungen für verschiedene Variationen der Frage. . . Es wird alles davon abhängen, welche Prioritäten für Ihre spezifische Situation gelten.
Talemyn


5

Eine gute ES6-Option wäre padStarteine leere Zeichenfolge. So was:

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

Hinweis: Dies funktioniert im IE nicht (ohne Polyfill).


3
s = '#'.repeat(10)Gibt es einen besonderen Grund, warum Sie diesen ES6-Ansatz gegenüber dem anderen ( ) aus der obigen Antwort von @ user4227915 empfehlen würden ?
Talemyn

@talemyn Einfachere Syntax
Mendy

3

Version, die in allen Browsern funktioniert

Diese Funktion macht, was Sie wollen, und arbeitet viel schneller als die in der akzeptierten Antwort vorgeschlagene Option:

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

Sie verwenden es so:

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

Um die Leistung dieser Funktion mit der der in der akzeptierten Antwort vorgeschlagenen Option zu vergleichen, finden Sie Benchmarks in dieser Geige und dieser Geige .

Version nur für moderne Browser

In modernen Browsern können Sie jetzt auch Folgendes tun:

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

Diese Option ist noch schneller. Leider funktioniert es in keiner Version des Internet Explorers.

Die Zahlen in der Tabelle geben die erste Browserversion an, die die Methode vollständig unterstützt:

Geben Sie hier die Bildbeschreibung ein


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

Sie können auch eine Polyfill für Repeat für ältere Browser hinzufügen

    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

Basierend auf Antworten von Hogan und Zero Trick Pony. Ich denke, dies sollte schnell und flexibel genug sein, um die meisten Anwendungsfälle gut zu bewältigen:

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

Bitte fügen Sie Ihrer Antwort weitere Erklärungen hinzu, da ein Code-Snippet selbst keine Antwort liefert.
Clijsters

@Leandro Clever und minimiert die Verarbeitung! +1
LMSingh

Ich denke, Sie meinten hash.length> = length
cipak

1

Sie können die erste Zeile der Funktion als Einzeiler verwenden, wenn Sie möchten:

function repeat(str, len) {
    while (str.length < len) str += str.substr(0, len-str.length);
    return str;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.