javascript - value - typescript split string into array




Javascript maneira elegante de dividir string em segmentos n caracteres longos (7)

Como o título diz, eu tenho uma string, e eu quero dividir em segmentos n caracteres de comprimento.

Por exemplo:

var str = 'abcdefghijkl';

depois de alguma magia com n = 3, vai se tornar

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

Existe uma maneira elegante de fazer isso?


Alguma solução limpa sem usar expressões regulares:

/**
* 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;
};

Exemplo de uso - https://jsfiddle.net/maciejsikora/b6xppj4q/ .

Eu também tentei comparar a minha solução para regexp uma que foi escolhida como resposta correta. Algum teste pode ser encontrado em jsfiddle - https://jsfiddle.net/maciejsikora/2envahrk/ . Testes estão mostrando que ambos os métodos têm desempenho similar, talvez na primeira olhada que a solução regexp é um pouco mais rápida, mas julgue você mesmo.


Aqui nós intercalamos uma string com outra string a cada n caracteres:

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;

};

se usarmos o acima como assim:

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

Nós temos:

aag | aag | aeg | eag | e

e aqui fazemos o mesmo, mas empurramos para um array:

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;

};

e depois executá-lo:

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

Nós temos:

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

se alguém souber de uma maneira de simplificar o código acima, lmk, mas ele deve funcionar bem para strings.


Com base nas respostas anteriores a esta pergunta; a seguinte função dividirá uma string ( str ) número-n ( size ) de caracteres.

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

Demonstração

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


Minha solução (sintaxe ES6):

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

Poderíamos até criar uma função com isso:

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

Então você pode chamar a função facilmente de uma maneira reutilizável:

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

Felicidades


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

Nota: Use {1,3} vez de apenas {3} para incluir o restante para comprimentos de string que não sejam múltiplos de 3, por exemplo:

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

Mais algumas sutilezas:

  1. Se sua string pode conter novas linhas ( que você quer contar como um caractere em vez de dividir a string ), então o arquivo . não vai capturar isso. Use /[\s\S]{1,3}/ vez disso. (Obrigado @Mike).
  2. Se a sua string estiver vazia, então match() retornará null quando você estiver esperando uma matriz vazia. Proteja-se contra isso anexando || [] || []

Então você pode acabar com:

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) || []);


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, []);

Solução limpa sem REGEX


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




split