매우 큰 문자열 (예 : 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' ]