web-dev-qa-db-fra.com

Manière élégante en Javascript de scinder une chaîne en segments de n caractères

Comme le titre l'indique, j'ai une chaîne et je veux me séparer en segments n caractères.

Par exemple:

var str = 'abcdefghijkl';

après un peu de magie avec n = 3, deviendra

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

Y a-t-il une manière élégante de faire ceci?

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

Remarque: Utilisez {1,3} au lieu de simplement {3} pour inclure le reste des longueurs de chaîne non multiples de 3, par exemple:

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

Quelques autres subtilités:

  1. Si votre chaîne peut contenir des nouvelles lignes ( que vous souhaitez comptabiliser en tant que caractère plutôt que de scinder la chaîne ), le . ne le sera pas. capturer ceux-ci. Utilisez /[\s\S]{1,3}/ à la place. (Merci @ Mike).
  2. Si votre chaîne est vide, alors match() renverra null lorsque vous attendez peut-être un tableau vide. Protégez-vous contre cela en ajoutant || [].

Donc, vous pouvez vous retrouver avec:

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

Si vous ne voulez pas utiliser une expression régulière ...

var chunks = [];

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

jsFiddle .

... sinon la solution regex est très bonne :)

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

S'appuyant sur les réponses précédentes à cette question; la fonction suivante divisera une chaîne (str) n-nombre (size) de caractères.

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

Démo

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

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

La fonction ci-dessus est ce que j'utilise pour le découpage en Base64. Cela créera un saut de ligne de 75 caractères.

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

Solution propre sans REGEX

1
seriouspat

Ma solution (syntaxe ES6):

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

Nous pourrions même créer une fonction avec ceci:

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

Ensuite, vous pouvez appeler la fonction facilement et de manière réutilisable:

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

À votre santé

1
Jesus Gonzalez

Quelques solutions propres sans utiliser d'expressions régulières:

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

Exemple d'utilisation - https://jsfiddle.net/maciejsikora/b6xppj4q/ .

J'ai aussi essayé de comparer ma solution à une expression rationnelle choisie comme bonne réponse. Certains tests peuvent être trouvés sur jsfiddle - https://jsfiddle.net/maciejsikora/2envahrk/ . Les tests montrent que les deux méthodes ont des performances similaires, peut-être que la solution regexp au premier abord est un peu plus rapide, mais jugez-en vous-même.

0
Maciej Sikora

Ici, nous entrecoupons une chaîne avec une autre chaîne tous les n caractères:

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;

};

si nous utilisons ce qui précède comme ceci:

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

on a:

aag | aag | aeg | eag | e

et ici nous faisons la même chose, mais Push to a 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;

};

puis lancez-le:

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

on a:

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

si quelqu'un connaît un moyen de simplifier le code ci-dessus, lmk, mais cela devrait fonctionner correctement pour les chaînes.

0
Alexander Mills

Avec .split:

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

et .replace sera:

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



/(?!$)/ doit s’arrêter avant end/$/, sans est:

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

ignorer le groupe /(?:...)/ n'est pas nécessaire dans .replace mais dans .split c'est ajouter des groupes à arr:

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

Voici un rapide deux lignes que les chiffres de commafies:

function commafy(inVal){
    var ary = String(inVal).match(/(\d{0,2})((?:\d{3})*)([^\d].*$)/i);
    return (ary[1] == "" ? [] : [ary[1]]).splice(1, 0, ary[2].match(/[0-9]{3}/g)).join(",") + ary[3];
}

si elle était étendue, cela pourrait ressembler à ceci:

function commafy(inVal){
    var aryChunks = [];
    var inVal = String(inVal);
    var aryPart1 = inVal.match(/(\d{0,2})((?:\d{3})*)([^\d].*$)/i);
    if(aryPart1[1] != ""){
        aryChunks.Push(aryPart1[1]);
    }
    var aryPart2 = aryPart1[2].match(/[0-9]{3}/g);
    aryChunks.splice(1, 0, aryPart2);
    var outVal = aryChunks.join(",");
    outVal += aryPart1[3];
    return outVal;
}

Tout d'abord, aryPart1 se voit attribuer une correspondance d'expression régulière composée de [0 à 2 chiffres], suivie de [chaîne de caractères dont la longueur est un multiple de 3], puis [zéro ou un non-chiffre et tout le reste].

Ensuite, si ce n'est pas "", nous ajoutons les [0 à 2 chiffres] à aryChunks. 

Après cela, nous prenons la [chaîne de caractères dont la longueur est un multiple de 3] et l'expression régulière leur correspond dans un tableau de [pièces de 3 caractères] appelé aryPart2, que nous joignons ensuite à aryChunks.

AryChunks contient maintenant les morceaux que nous allons associer avec une virgule et assigner à outVal.

Tout ce qui reste à faire est d'ajouter le [zéro ou un non-chiffre et tout le reste] à outVal et de renvoyer outVal à l'appelant.

Selon l'OP, {0,2} et {3} dans l'expression rationnelle 1 et le {3} dans l'expression rationnelle 2 peuvent être des variables permettant de donner aux morceaux une longueur quelconque, et le\d dans les expressions rationnelles peut être remplacé par "." si vous voulez que cela fonctionne sur plus que des chiffres.

J'ai passé trop de temps à l'écrire, il y a donc peut-être quelques problèmes. Pointez-les et je les bidouillerai.

0
alfadog67