Dividir una cadena en una letra mayúscula o números


9

Estaba tratando de hacer una tubería en mecanografiado que dividiría una cadena PascalCase, pero sería bueno si esto también se dividiera en dígitos. También me gustaría que se dividiera en letras mayúsculas consecutivas. Tengo esta tubería, que funciona muy bien, excepto que solo funciona en Chrome y no en Firefox, evidentemente solo Chrome admite mirar hacia atrás. ¿Cómo se puede lograr esto sin mirar atrás?

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

Entonces, por ejemplo, una cadena ANet15Amountdebe transformarse en A Net 15 Amount. Esta expresión regular anterior también dividiría una cadena camelCase, pero eso no es necesario tener en cuenta.


.replace(/([A-Z]|\d+)/g, " $1").trim();
ibrahim mahrir

2
@ibrahimmahrir (?!^)([A-Z]|\d+)evita el primer espacio y no necesita recortar.
ctwheels

Respuestas:


6

¿Qué tal unir con un patrón más básico como este y unir con el espacio?

let str = `ANet15Amount`;

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

console.log(camel);

Primero pensé simplemente, [A-Z][a-z]*|\d+pero esto se dividiría, por ejemplo, ABCDefg123en lo A B C Defg 123que sería diferente trabajar para su función actual, que se transforma en ABC Defg 123.

Todavía hay una pequeña diferencia. El suyo transforma A1B2a A 1B 2y éste a A 1 B 2donde creo que éste sería más exacto, no es así.


1
Brillante, pasó todos mis casos de prueba. Estoy de acuerdo, el tuyo es más preciso. ¡Realmente lo aprecio!
develmatik

@develmatik Me alegro de que funcione como lo deseé, acabo de leer sobre las diferencias de Camel con PascalCase :)
burbuja de burbuja el

3

Simplemente reemplace cualquier letra mayúscula [A-Z]o cualquier secuencia de dígitos \d+con un espacio más lo que acabamos de hacer coincidir " $1". Omitimos la primera letra para que no se agregue espacio al comienzo de la cadena resultante agregando un aspecto negativo al comienzo de la cadena (?!^):

// ...

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

Ejemplo:


2

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

  • 0 o 1 letra mayúscula seguida directamente por 1 o más letras minúsculas
  • o 1 letra mayúscula
  • o 1 o más dígitos

Prueba en generador: https://regex101.com/r/uBO0P5/1


2

Supongo que depende de las convenciones de la cadena que pueden aumentar la complejidad.

// 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(' ')
);

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.