반복되는 문자로 채워진 가변 길이의 문자열을 만듭니다.


164

그래서 내 질문은 다른 사람이 Java 형식으로 여기에서 물었습니다 : Java-지정된 길이의 새 문자열 인스턴스를 만들고 특정 문자로 채 웁니다. 최고의 솔루션?

. . . 하지만 JavaScript와 동등한 것을 찾고 있습니다.

기본적으로 각 필드의 "maxlength"속성에 따라 텍스트 필드를 "#"문자로 동적으로 채우려 고합니다. 따라서 입력에가 있으면 maxlength="3"필드는 "###"으로 채워집니다.

이상적으로 Java와 같은 것이 StringUtils.repeat("#", 10);있지만 지금까지 내가 생각할 수있는 가장 좋은 옵션은 최대 길이에 도달 할 때까지 한 번에 하나씩 "#"문자를 반복하여 추가하는 것입니다. 그보다 더 효율적인 방법이 있다는 느낌을 흔들 수 없습니다.

어떤 아이디어?

참고로 "#"문자는 포커스를 지우고 사용자가 값을 입력하지 않은 경우 흐림시 "리필"해야하기 때문에 입력에서 기본값을 간단히 설정할 수 없습니다. 내가 관심있는 "리필"단계


1
입력 필드의 텍스트를 마스크하기 위해이 작업을 수행하고 있습니까?
Feisty Mango

@ MatthewCox : 아니요, maxlength의 시각적 표시를 제공하는 것이 더 좋습니다. 이 경우 번호의 3 개 부분으로 분할 된 일련의 전화 번호 필드입니다. 처음 2 개의 필드에는 3 자리 숫자가 필요하고 마지막에는 4
개가

답변:


303

이 작업을 수행하는 가장 좋은 방법은

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

주어진 길이의 배열을 만든 다음 주어진 문자열과 결합하여 반복합니다. 이 .join()함수는 요소에 값이 할당되어 있는지 여부에 관계없이 배열 길이를 유지하며 정의되지 않은 값은 빈 문자열로 렌더링됩니다.

구분자 문자열이 배열 요소 사이 에 있으므로 원하는 길이에 1을 추가해야합니다 .


못을 박았다 :) 방금 parseInt()입력 크기를 사용하기 전에 입력 maxlength 값 을 사용해야한다는 것을 기억해야 했습니다. 내가 찾던 것. . . 감사!
talemyn

11
이 솔루션은 매우 느립니다. 그것은 섹시 해 보이지만 아마도 이것을하는 잘못된 방법 일 것입니다.
Hogan

23
repeatString.prototype에 내장 된 새로운 함수는 이제 이것을 처리합니다 (ES6 +)
AlexMA

아픈 해결책. 감사합니다!
C4d

156

이것을 시도하십시오 : P

s = '#'.repeat(10)

document.body.innerHTML = s


4
ECMAScript 6의 일부이므로 확실히 가장 쉬운 구현이지만 가장 적게 지원됩니다. Firefox, Chrome 및 데스크톱 버전의 Safari에서만 지원되는 것처럼 보입니다.
talemyn

5
lodash를 사용하지 않는다면 다음을 사용할 수 있습니다. _.repeat('*',10);
Geraud Gratacap

4
이제 2018 년이며 ES6이 올바르게 설정되었습니다. 이것이 받아 들여야합니다. Babel 또는 이와 유사한 것을 사용하지 않는 브라우저에서 레거시 브라우저를 지원해야하는 경우 위에서 언급 한대로 lodash를 사용하거나 백업을 위해 polyfill을 사용할 수 있습니다.
seanTcoyote

@seanTcoyote 내가 원하는만큼 IE 11 및 Adroid의 Webview와 경쟁 해야하는 사람들이 여전히 repeat()있습니다. 내가 더 이상 신경 쓰지 않아도 될 날을 기대합니다. . .
talemyn

불행히도, 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 방식보다 2X에서 10X 사이에서 더 나은 성능을 발휘하며 작은 입력에 대한 배가 구현보다 빠릅니다. 암호:

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

@Hogan 솔루션은 아무데도 채워진 문자열을 만들지 않습니다. 직접 작성하고 부분 문자열을 추출하십시오.
StanE

이 방법은 매우 큰 문자열의 경우 Node.js에서 Array.join보다 10 배 느립니다.
Anshul Koka

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 자 이상이 필요하지 않습니다. 유스 케이스에 더 많은 문자가 필요한 경우 문자열을 다시 업데이트해야합니다. 다른 두 솔루션은 이와 관련하여 더 많은 유연성을 허용합니다. 그러나 속도는 +1입니다.
talemyn

1
아, 그리고 반대로 (그리고 나는 이것이 프로그래밍 방식보다 스타일에 대한 관심사라는 것을 알고 있습니다), 3-4 문자에만 사용되는 30 + 문자열을 유지하면 나도 . . . 다시, 다양한 사용 사례에 대한 솔루션의 유연성과 관련된 사소한 문제입니다.
talemyn

@talemyn IT에서는 모든 것이 절충됩니다. 4 개의 문자열을 가지고 더 크게 만들거나 30 개의 문자열을 가지고 걱정하지 마십시오. 대체로, 크기가 1k에 달하는 일정한 문자열은 최신 머신에서 작은 자원 사용입니다.
Hogan

@Hogan-전적으로 동의합니다. . . 이것이 실제로 속도에 중점을 두지 않은 이유의 일부입니다. 특정 사용 사례에서는 길이가 3, 3 및 4자인 3 개의 문자열을 찾고있었습니다. Pointy의 솔루션은 가장 느 렸지만 줄이 짧고 그 중 몇 개만 있었기 때문에 간결하고 읽기 쉽고 유지 관리하기 쉽다는 사실을 좋아했기 때문에 함께했습니다. 결국, 그들은 질문의 다른 변형에 대한 좋은 해결책입니다. . . 그것은 모두 특정 상황에 대한 우선 순위가 무엇인지에 달려 있습니다.
talemyn


5

훌륭한 ES6 옵션은 padStart빈 문자열입니다. 이처럼 :

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

참고 : 이것은 IE에서 작동하지 않습니다 (polyfill없이).


3
특히 s = '#'.repeat(10)@ user4227915의 답변에서 다른 ES (6 )보다이 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);

이 함수의 성능과 허용 된 답변에서 제안 된 옵션의 성능을 비교하려면 이 Fiddle이 Fiddle 에서 벤치 마크를 참조하십시오 .

최신 브라우저 전용 버전

최신 브라우저에서는 다음을 수행 할 수도 있습니다.

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

코드 스 니펫 자체가 답변을 제공하지 않으므로 답변에 설명을 추가하십시오.
Clijsters

@Leandro Clever는 처리를 최소화합니다! +1
LMSingh

나는 당신이 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.