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.

develmatik
fuente
.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í.

burbuja bobble
fuente
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:

ibrahim mahrir
fuente
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

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

1O1
fuente