[javascript] JavaScript에서 큰 문자열을 n 크기 청크로 분할

매우 큰 문자열 (예 : 10,000 문자)을 N 크기 청크로 나누고 싶습니다.

이를 수행하기위한 성능 측면에서 가장 좋은 방법은 무엇입니까?

예를 들어
"1234567890", 2로 나누면이 ["12", "34", "56", "78", "90"]됩니다.

이것을 사용하여 가능 String.prototype.match합니까? 그렇다면 성능 측면에서 가장 좋은 방법입니까?



답변

다음과 같이 할 수 있습니다 :

"1234567890".match(/.{1,2}/g);
// Results in:
["12", "34", "56", "78", "90"]

이 방법은 크기가 청크 크기의 정확한 배수가 아닌 문자열에서 계속 작동합니다.

"123456789".match(/.{1,2}/g);
// Results in:
["12", "34", "56", "78", "9"]

일반적으로 가장 큰 n 크기의 하위 문자열 을 추출하려는 문자열에 대해 다음을 수행하십시오.

str.match(/.{1,n}/g); // Replace n with the size of the substring

문자열에 줄 바꿈 또는 캐리지 리턴이 포함될 수 있으면 다음을 수행하십시오.

str.match(/(.|[\r\n]){1,n}/g); // Replace n with the size of the substring

성능에 관해서는 약 10k 자로이 작업을 시도했으며 Chrome에서 1 초가 조금 걸렸습니다. YMMV.

재사용 가능한 함수에서도 사용할 수 있습니다.

function chunkString(str, length) {
  return str.match(new RegExp('.{1,' + length + '}', 'g'));
}


답변

jsPerf에서 볼 수있는 몇 가지 더 빠른 변형을 만들었습니다 . 내가 가장 좋아하는 것은 다음과 같습니다.

function chunkSubstr(str, size) {
  const numChunks = Math.ceil(str.length / size)
  const chunks = new Array(numChunks)

  for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
    chunks[i] = str.substr(o, size)
  }

  return chunks
}


답변

결론 :

  • match매우 비효율적이다 slice파이어 폭스, 더 substr/ substring더 나은 여전히
  • match 캐시 된 정규 표현식을 사용하더라도 정규 표현식 구문 분석 설정 시간으로 인해 짧은 문자열에 대해 훨씬 비효율적입니다.
  • match 큰 청크 크기에 대해서는 훨씬 더 비효율적입니다 (아마 “점프”할 수 없기 때문).
  • 청크 크기가 매우 작은 더 긴 문자열의 경우 이전 IE 에서는 match성능이 slice뛰어나지 만 다른 모든 시스템에서는 여전히 손실됩니다
  • jsperf 바위

답변

이것은 빠르고 간단한 솔루션입니다.

function chunkString (str, len) {
  const size = Math.ceil(str.length/len)
  const r = Array(size)
  let offset = 0

  for (let i = 0; i < size; i++) {
    r[i] = str.substr(offset, len)
    offset += len
  }

  return r
}

console.log(chunkString("helloworld", 3))
// => [ "hel", "low", "orl", "d" ]

// 10,000 char string
const bigString = "helloworld".repeat(1000)
console.time("perf")
const result = chunkString(bigString, 3)
console.timeEnd("perf")
console.log(result)
// => perf: 0.385 ms
// => [ "hel", "low", "orl", "dhe", "llo", "wor", ... ]


답변

놀라다! split 을 사용하여 분할 할 수 있습니다 .

var parts = "1234567890 ".split(/(.{2})/).filter(O=>O)

결과 [ '12', '34', '56', '78', '90', ' ' ]


답변

var str = "123456789";
var chunks = [];
var chunkSize = 2;

while (str) {
    if (str.length < chunkSize) {
        chunks.push(str);
        break;
    }
    else {
        chunks.push(str.substr(0, chunkSize));
        str = str.substr(chunkSize);
    }
}

alert(chunks); // chunks == 12,34,56,78,9


답변

확장 된 함수를 작성 했으므로 청크 길이는 [1,3]과 같은 숫자 배열도 될 수 있습니다.

String.prototype.chunkString = function(len) {
    var _ret;
    if (this.length < 1) {
        return [];
    }
    if (typeof len === 'number' && len > 0) {
        var _size = Math.ceil(this.length / len), _offset = 0;
        _ret = new Array(_size);
        for (var _i = 0; _i < _size; _i++) {
            _ret[_i] = this.substring(_offset, _offset = _offset + len);
        }
    }
    else if (typeof len === 'object' && len.length) {
        var n = 0, l = this.length, chunk, that = this;
        _ret = [];
        do {
            len.forEach(function(o) {
                chunk = that.substring(n, n + o);
                if (chunk !== '') {
                    _ret.push(chunk);
                    n += chunk.length;
                }
            });
            if (n === 0) {
                return undefined; // prevent an endless loop when len = [0]
            }
        } while (n < l);
    }
    return _ret;
};

코드

"1234567890123".chunkString([1,3])

돌아올 것이다 :

[ '1', '234', '5', '678', '9', '012', '3' ]