Fractionner une chaîne sur une lettre majuscule ou des chiffres

9

J'essayais de créer un tube en texte dactylographié qui diviserait une chaîne PascalCase, mais ce serait bien si cela se divisait également en chiffres. J'aimerais également qu'il se divise en majuscules consécutives. J'ai ce tuyau, qui fonctionne très bien, sauf qu'il ne fonctionne que dans Chrome et non Firefox, évidemment, seul Chrome prend en charge les rétrospectifs. Comment peut-on accomplir cela sans regarder en arrière?

transform(value: string): string {
        let extracted = '';
        if (!value) {
            return extracted;
        }

        const regExSplit = value
            .split(new RegExp('(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[0-9])(?=[A-Z][a-z])|(?<=[a-zA-Z])(?=[0-9])'));
        for (let i = 0; i < regExSplit.length; i++) {
            if (i !== regExSplit.length - 1) {
                extracted += `${regExSplit[i]} `;
            } else {
                extracted += regExSplit[i];
            }
        }

        return extracted;
    }

Ainsi, par exemple, une chaîne ANet15Amountdoit être transformée en A Net 15 Amount. Cette expression régulière ci-dessus diviserait également une chaîne camelCase, mais ce n'est pas nécessaire à prendre en compte.

develmatik
la source
.replace(/([A-Z]|\d+)/g, " $1").trim();
ibrahim mahrir
2
@ibrahimmahrir (?!^)([A-Z]|\d+)évite le premier espace et n'a pas besoin d'ajustement.
ctwheels

Réponses:

6

Que diriez-vous de l' appariement par un motif plus basique comme celui-ci et de rejoindre l' espace.

let str = `ANet15Amount`;

let camel = str.match(/[A-Z]+(?![a-z])|[A-Z]?[a-z]+|\d+/g).join(' ');

console.log(camel);

D'abord, j'ai pensé simplement, [A-Z][a-z]*|\d+mais cela se briserait par exemple ABCDefg123en A B C Defg 123ce qui serait différent en fonction de votre fonction actuelle, qui se transforme en ABC Defg 123.

Il y a encore une petite différence. Le vôtre se transforme A1B2en A 1B 2celui-ci A 1 B 2où je pense que celui-ci serait plus précis, n'est-ce pas.

bulle de pompon
la source
1
Brillant, a réussi tous mes tests. Je suis d'accord, le vôtre est plus précis. J'apprécie vraiment cela!
develmatik
@develmatik Heureux que cela fonctionne comme souhaité, je viens de lire les différences entre Camel et PascalCase :)
bulle de
3

Remplacez simplement toute lettre majuscule [A-Z]ou toute séquence de chiffres \d+par un espace plus ce que nous venons de faire correspondre " $1". Nous sautons la première lettre afin qu'aucun espace ne soit ajouté au début de la chaîne résultante en ajoutant un lookahead négatif au début de la chaîne (?!^):

// ...

return value.replace(/(?!^)([A-Z]|\d+)/g, " $1");

Exemple:

ibrahim mahrir
la source
2

Essayer [A-Z]?[a-z]+|[A-Z]|[0-9]+

  • 0 ou 1 lettre majuscule directement suivie par 1 ou plusieurs lettres minuscules
  • ou 1 lettre majuscule
  • ou 1 ou plusieurs chiffres

Test dans le générateur: https://regex101.com/r/uBO0P5/1

Tony
la source
2

Je suppose que cela dépend des conventions de la chaîne, ce qui peut augmenter la complexité

// here 'TIMES' & 'with' are seperated (example 2)
const str = 'SplittingStringsIsFunTimesA100000aaaTIMESwithFollowUp';

// here 'TIMES' & 'With' are seperated (exmpaple 3)
const str2 = 'SplittingStringsIsFunTimesA100000aaaTIMESWithCAPITAL5FollowUp';


// 1. USING REGEX - MATCH
console.log(
  '1. USING REGEX:\n',
  str
  .match(/(\d+|[a-z]+|[A-Z][a-z]*)/g)
  .join(' ')
);


// 2. USING REGEX - MATCH (KEEP ALL CAPITAL CHARS)
console.log(
  '2. USING REGEX (GROUP ALL):\n',
  str
  .match(/(\d+|[a-z]+|([A-Z]([A-Z]+|[a-z]*)))/g)
  .join(' ')
);

// 3. USING REGEX - MATCH (KEEP CAPITAL CHARS BUT LAST)
console.log(
  '3. USING REGEX (GROUP BUT LAST):\n',
  str2
  .match(/(\d+|[a-z]+|([A-Z]([a-z]+|([A-Z]+(?![a-z]))?)))/g)
  .join(' ')
);


// 4. USING SPLIT - FILTER
console.log(
  '4. USING SPLIT:\n',
  str2
  .split(/(\d+|[A-Z][a-z]*)/)
  .filter(v => v !== '')
  .join(' ')
);

1O1
la source