Bir dizeyi n karakterlik segmentlere nasıl bölebilirim?


203

Başlığın dediği gibi, bir dizem var ve n karakterlik segmentlere ayırmak istiyorum .

Örneğin:

var str = 'abcdefghijkl';

biraz sihirden sonra n=3,

var arr = ['abc','def','ghi','jkl'];

Bunu yapmanın bir yolu var mı?

Yanıtlar:


361

var str = 'abcdefghijkl';
console.log(str.match(/.{1,3}/g));

Not: Kullanım {1,3}yerine sadece {3}3'ün tam katı, örneğin değildir dize uzunlukları için kalan içerecek şekilde:

console.log("abcd".match(/.{1,3}/g)); // ["abc", "d"]


Birkaç incelik daha:

  1. Dizeniz yeni satırlar içeriyorsa ( dizeyi bölmek yerine karakter olarak saymak istediğinizde ), .bunları yakalamaz. /[\s\S]{1,3}/Bunun yerine kullanın . (Teşekkürler @Mike).
  2. Dizeniz boşsa, boş bir dizi beklediğinizde match()geri döner null. Ekleyerek buna karşı koruyun || [].

Sonuç olarak:

var str = 'abcdef \t\r\nghijkl';
var parts = str.match(/[\s\S]{1,3}/g) || [];
console.log(parts);

console.log(''.match(/[\s\S]{1,3}/g) || []);


Bu teknik olarak daha iyi bir cevaptır, çünkü 3 ile eşit olarak bölünemeyen bir dizeden tüm metni alacaktır (son 2 veya 1 karakteri alacaktır).
Erik

6
Yeni satırlarda başarısız olmamak [\s\S]yerine kullanın ..
Mike Samuel

2
Her satırda yeni bir döngü başlatmak isteyebilirsiniz. Gerçekten yeni satırlarınız varsa, muhtemelen bir tür geçiş olduğunu gösterirler. str.match (/. {1,3} / gm) daha iyi bir seçim olabilir.
kennebec

+1 Dikkat: ''.match(/.{1,3}/g) ve boş bir dizi yerine ''.match(/.{3}/g)geri dönün null.
Web_Designer

4
3 numara yerine değişken olması mümkün müdür?
Ana Claudia

46

Normal bir ifade kullanmak istemediyseniz ...

var chunks = [];

for (var i = 0, charsLength = str.length; i < charsLength; i += 3) {
    chunks.push(str.substring(i, i + 3));
}

jsFiddle .

... aksi takdirde normal ifade çözümü oldukça iyi :)


1
+1 çünkü 3OP tarafından önerilen değişken ise bunu tercih ederim . Normal ifade dizesini birleştirmekten daha okunabilir.
David Tang

sadece kullanıma hazır kullanışlı bir işleve sarın
mmm

1
Bu regex seçeneğinden 10 kat daha hızlı, bu yüzden (işlev içinde) ile giderdim jsbench.github.io/#9cb819bf1ce429575f8535a211f72d5a
Job

1
Önceki ifadem Chromium için de geçerlidir (ayrıca, önceki yorumu düzenlemek için çok geç kaldım, dolayısıyla yenisini). Firefox'ta şu anda makinemde "sadece"% 30 daha hızlı, ancak bu hala daha iyi.
Meslek

Bu uzun ipler boyunca sürdürülebilir mi?
Jacob Schneider

22
str.match(/.{3}/g); // => ['abc', 'def', 'ghi', 'jkl']

Bu çalışır 3benim ama iadeler için nullbirlikte 250. 🤔
Jim

9

Bu sorunun daha önceki cevaplarına dayanarak; aşağıdaki işlev bir karakter dizisini ( str) n-sayısı ( size) böler .

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

gösteri

(function() {
  function chunk(str, size) {
    return str.match(new RegExp('.{1,' + size + '}', 'g'));
  }
  
  var str = 'HELLO WORLD';
  println('Simple binary representation:');
  println(chunk(textToBin(str), 8).join('\n'));
  println('\nNow for something crazy:');
  println(chunk(textToHex(str, 4), 8).map(function(h) { return '0x' + h }).join('  '));
  
  // Utiliy functions, you can ignore these.
  function textToBin(text) { return textToBase(text, 2, 8); }
  function textToHex(t, w) { return pad(textToBase(t,16,2), roundUp(t.length, w)*2, '00'); }
  function pad(val, len, chr) { return (repeat(chr, len) + val).slice(-len); }
  function print(text) { document.getElementById('out').innerHTML += (text || ''); }
  function println(text) { print((text || '') + '\n'); }
  function repeat(chr, n) { return new Array(n + 1).join(chr); }
  function textToBase(text, radix, n) {
    return text.split('').reduce(function(result, chr) {
      return result + pad(chr.charCodeAt(0).toString(radix), n, '0');
    }, '');
  }
  function roundUp(numToRound, multiple) { 
    if (multiple === 0) return numToRound;
    var remainder = numToRound % multiple;
    return remainder === 0 ? numToRound : numToRound + multiple - remainder;
  }
}());
#out {
  white-space: pre;
  font-size: 0.8em;
}
<div id="out"></div>


2

Çözümüm (ES6 sözdizimi):

const source = "8d7f66a9273fc766cd66d1d";
const target = [];
for (
    const array = Array.from(source);
    array.length;
    target.push(array.splice(0,2).join(''), 2));

Bununla bir fonksiyon bile oluşturabiliriz:

function splitStringBySegmentLength(source, segmentLength) {
    if (!segmentLength || segmentLength < 1) throw Error('Segment length must be defined and greater than/equal to 1');
    const target = [];
    for (
        const array = Array.from(source);
        array.length;
        target.push(array.splice(0,segmentLength).join('')));
    return target;
}

Ardından işlevi yeniden kullanılabilir bir şekilde kolayca çağırabilirsiniz:

const source = "8d7f66a9273fc766cd66d1d";
const target = splitStringBySegmentLength(source, 2);

Şerefe


2
const chunkStr = (str, n, acc) => {     
    if (str.length === 0) {
        return acc
    } else {
        acc.push(str.substring(0, n));
        return chunkStr(str.substring(n), n, acc);
    }
}
const str = 'abcdefghijkl';
const splittedString = chunkStr(str, 3, []);

REGEX olmadan temiz çözüm


1
function chunk(er){
return er.match(/.{1,75}/g).join('\n');
}

Yukarıdaki fonksiyon Base64 parçaları için kullandığım şey. 75 karaktere kadar bir satır sonu oluşturur.


Ayrıca yapabilirdi replace(/.{1,75}/g, '$&\n').
alex

1

Burada, her n karakterde bir dize ile başka bir dize serpiştiriyoruz:

export const intersperseString = (n: number, intersperseWith: string, str: string): string => {

  let ret = str.slice(0,n), remaining = str;

  while (remaining) {
    let v = remaining.slice(0, n);
    remaining = remaining.slice(v.length);
    ret += intersperseWith + v;
  }

  return ret;

};

yukarıdaki gibi kullanırsak:

console.log(splitString(3,'|', 'aagaegeage'));

elde ederiz:

aag | aag | aeg | eag | e

burada da aynısını yapıyoruz, ama bir diziye geçiyoruz:

export const sperseString = (n: number, str: string): Array<string> => {

  let ret = [], remaining = str;

  while (remaining) {
    let v = remaining.slice(0, n);
    remaining = remaining.slice(v.length);
    ret.push(v);
  }

  return ret;

};

ve sonra çalıştırın:

console.log(sperseString(5, 'foobarbaztruck'));

elde ederiz:

['fooba', 'rbazt', 'ruck']

Birisi yukarıdaki kodu basitleştirmenin bir yolunu biliyorsa, lmk, ancak dizeler için iyi çalışmalıdır.


ilk snippet'iniz beklendiği gibi çalışmadı. Burada değiştirdim: jsfiddle.net/omarojo/ksvx2txb/261
omarojo

0

Düzenli ifadeler kullanmadan temiz bir çözüm:

/**
* Create array with maximum chunk length = maxPartSize
* It work safe also for shorter strings than part size
**/
function convertStringToArray(str, maxPartSize){

  const chunkArr = [];
  let leftStr = str;
  do {

    chunkArr.push(leftStr.substring(0, maxPartSize));
    leftStr = leftStr.substring(maxPartSize, leftStr.length);

  } while (leftStr.length > 0);

  return chunkArr;
};

Kullanım örneği - https://jsfiddle.net/maciejsikora/b6xppj4q/ .

Ayrıca, doğru cevap olarak seçilen regexp ile çözümümü karşılaştırmaya çalıştım. Bazı testler jsfiddle - https://jsfiddle.net/maciejsikora/2envahrk/ adresinde bulunabilir . Testler, her iki yöntemin de benzer performansa sahip olduğunu gösteriyor, belki de ilk bakışta normal ifade çözümünün biraz daha hızlı olduğunu, ancak Kendinizi yargılayacağınızı gösteriyor.


0

İle .split:

var arr = str.split( /(?<=^(?:.{3})+)(?!$)/ )  // [ 'abc', 'def', 'ghi', 'jkl' ]

ve .replaceolacak:

var replaced = str.replace( /(?<=^(.{3})+)(?!$)/g, ' || ' )  // 'abc || def || ghi || jkl'



/(?!$)/bitmeden durmaktır /$/, olmadan:

var arr      = str.split( /(?<=^(?:.{3})+)/ )        // [ 'abc', 'def', 'ghi', 'jkl' ]     // I don't know why is not [ 'abc', 'def', 'ghi', 'jkl' , '' ], comment?
var replaced = str.replace( /(?<=^(.{3})+)/g, ' || ')  // 'abc || def || ghi || jkl || '

grup görmezden /(?:... )/mi gerek .replaceama .splitarr için grupları ekliyor:

var arr = str.split( /(?<=^(.{3})+)(?!$)/ )  // [ 'abc', 'abc', 'def', 'abc', 'ghi', 'abc', 'jkl' ]

0

Düzenli ifadeler veya açık döngüler olmadan bunu yapmanın bir yolu, ancak bir astarın tanımını biraz uzatıyor:

const input = 'abcdefghijlkm';

// Change `3` to the desired split length.
const output = input.split('').reduce((s, c) => {let l = s.length-1; (s[l] && s[l].length < 3) ? s[l] += c : s.push(c); return s;}, []);

console.log(output);  // output: [ 'abc', 'def', 'ghi', 'jlk', 'm' ]

Dizeyi tek tek karakter dizisine bölerek Array.reduceher karakterin üzerinde yineleme yapmak için kullanılır . Normalde reducetek bir değer döndürür, ancak bu durumda tek değer bir dizi olur ve her karakterin üzerinden geçerken onu bu dizideki son öğeye ekleriz. Dizideki son öğe hedef uzunluğa ulaştığında, yeni bir dizi öğesi ekleriz.


0

Biraz sonra tartışmaya geliyoruz ama burada subring + dizisinden biraz daha hızlı bir varyasyon itiyor.

// substring + array push + end precalc
var chunks = [];

for (var i = 0, e = 3, charsLength = str.length; i < charsLength; i += 3, e += 3) {
    chunks.push(str.substring(i, e));
}

For döngüsünün bir parçası olarak bitiş değerini önceden hesaplamak, alt dize içinde satır içi matematik yapmaktan daha hızlıdır. Firefox ve Chrome'da test ettim ve ikisi de hızlanma gösteriyor.

Burada deneyebilirsin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.