繰り返される文字で満たされた可変長の文字列を作成する


164

だから、私の質問はここのJavaフォームで誰かに尋ねられました:Java-指定された長さで特定の文字で満たされた新しいStringインスタンスを作成します。最善の解決策は?

。。。しかし、私はそれに相当するJavaScriptを探しています。

基本的に、各フィールドの「maxlength」属性に基づいて、テキストフィールドに「#」文字を動的に入力します。したがって、入力にhasがmaxlength="3"ある場合、フィールドは「###」で埋められます。

理想的にはJavaのようなものが存在しますStringUtils.repeat("#", 10);が、これまでのところ、私が考えることができる最良のオプションは、最大長に達するまで「#」文字を1つずつループして追加することです。それよりももっと効率的な方法があるという気持ちを揺さぶることはできません。

何か案は?

参考:入力にデフォルト値を設定することはできません。「#」文字はフォーカスをクリアする必要があり、ユーザーが値を入力しなかった場合は、ぼかしで「補充」する必要があるためです。それは私が心配している「補充」のステップです


1
入力フィールドのテキストをマスクするためにこれを行っていますか?
Feisty Mango 2013

@MatthewCox:いいえ、maxlengthの視覚的な表示を提供するだけではありません。この場合は、番号の3つの部分に分割される一連の電話番号フィールド用です。これは、最初の2つのフィールドが4 3桁と最後のニーズが必要であることを示すだろう
talemyn

回答:


302

これを行う最良の方法(私が見たもの)は

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

これにより、指定された長さの配列が作成され、指定された文字列と結合されて繰り返されます。この.join()関数は、要素に値が割り当てられているかどうかに関係なく配列の長さを尊重し、未定義の値は空の文字列としてレンダリングされます。

区切り文字列は配列要素の間にあるため、希望の長さに1を加える必要があります。


ばっちり成功。:) parseInt()配列のサイズを設定する前に、入力のmaxlength値を使用することを覚えておく必要がありました。ちょうど私が探していたもの。。。ありがとう!
talemyn 2013年

11
このソリューションは非常に遅いことに注意してください。見た目はセクシーですが、これはおそらく間違った方法です。
Hogan

23
repeatString.prototypeに組み込まれた新しい関数がこれを処理する(ES6 +)
AlexMA

病気のソリューション。それをありがとう!
C4d

156

これを試してみてください:P

s = '#'.repeat(10)

document.body.innerHTML = s


4
間違いなく最も簡単な実装ですが、ECMAScript 6の一部であるため、サポートも最低限です。現在のところ、SafariのFirefox、Chrome、デスクトップバージョンでのみサポートされています。
talemyn

5
あなたが使用して気にしない場合はlodashを:は、次の使用することができます _.repeat('*',10);
ジェローGratacap

4
現在は2018年であり、ES6は十分に確立されています。また、Babelなどを使用していないユーザーのためにレガシーブラウザをサポートする必要がある場合は、上記のlodashを使用するか、バックアップにポリフィルを使用できます。
seanTcoyote 2018年

@seanTcoyoteできるだけ多くのrepeat()方法で、IE 11やAdroidのWebviewと競合しなければならない人がまだいますが、どちらもメソッドをサポートしていません。もう気にする必要のない日を楽しみにしています。。。
talemyn 2018

残念ながら、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倍優れたパフォーマンスを発揮し、小さな入力の2倍の実装よりも高速です。コード:

// 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桁)。
ホーガン

@Hoganソリューションはどこからでも文字列を作成しません。自分で作成し、部分文字列を抽出します。
StanE

このアプローチは、非常に大きな文字列の場合、Node.jsのArray.joinよりも10倍遅くなります。
Anshul Koka 2017

21

定数文字列を作成してから、その部分文字列を呼び出します。

何かのようなもの

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

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

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

もう少し速い。

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


1
これはとても賢いです!また、複数の文字を含む文字列パターンでも機能します。
Markus

1
多くの注目を集め続けているようで、あなたのソリューションについてコメントしたかったので、このページを再訪してください。あなたのアプローチのシンプルさとスピードは間違いなく気に入っていますが、私の最大の懸念はメンテナンス/再利用にありました。私の特定のシナリオでは、ジェネリック関数として4文字を超える必要はありませんでしたが、固定長の文字列を使用すると、ユースケースで文字がさらに必要になる場合は、戻って文字列を更新する必要があります。他の2つのソリューションでは、その点でより柔軟に対応できます。ただし、速度は+1です。
talemyn 2015年

1
ああ、そして裏側では(これはプログラマティックなものよりもスタイルの問題のほうが本当に多いと思います)、3〜4文字にしか使用されない30文字以上の文字列を維持すると、私もです 。。。繰り返しになりますが、さまざまなユースケースに対するソリューションの柔軟性に関する小さな問題です。
talemyn 2015年

@talemyn ITでは、すべてがトレードオフです。4文字の文字列でそれを大きくするか、30文字の文字列で問題ありません。全体として、任意のサイズの一定の文字列(1kでも)は、最新のマシンでの小さなリソース使用量です。
Hogan、

@Hogan-完全に同意します。。。そして、それは私がスピードにもあまり重点を置かなかった理由の一部です。私の特定の使用例では、長さが3、3、および4文字の3つの文字列を探していました。Pointyのソリューションは最も低速でしたが、文字列が短く、数が少なかったため、合理化され、読みやすく、保守が容易であるという事実が気に入ったので、彼と一緒に行きました。結局、これらはすべて、質問のさまざまなバリエーションに対する優れたソリューションです。。。それはすべて、特定の状況の優先順位が何であるかに依存します。
talemyn 2015年


5

padStart空の文字列に対するES6の優れたオプションは、このような:

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

注:これはIEでは機能しません(ポリフィルがない場合)。


3
s = '#'.repeat(10)上記の@ 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);

この関数のパフォーマンスを、承認済みの回答で提案されているオプションのパフォーマンスと比較するには、このフィドルこのフィドルのベンチマークを参照してください。

最新のブラウザのみのバージョン

最近のブラウザでは、これもできるようになりました:

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

コードスニペット自体は回答を提供しないため、回答に説明を追加してください。
クライシュテルス

@Leandro Cleverと処理を最小限に抑える!+1
LMSing 2017

hash.length> = length
cipak

1

必要に応じて、関数の最初の行をワンライナーとして使用できます。

function repeat(str, len) {
    while (str.length < len) str += str.substr(0, len-str.length);
    return str;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.