Dividir uma string em uma letra maiúscula ou em números


9

Eu estava tentando fazer um pipe no texto datilografado que dividisse uma string PascalCase, mas seria bom se isso também fosse dividido em dígitos. Eu também gostaria que fosse dividido em maiúsculas consecutivas. Eu tenho esse pipe, que funciona muito bem, exceto que funciona apenas no Chrome e não no Firefox, evidentemente, apenas o Chrome oferece suporte ao visual. Como conseguir isso sem olhar para trá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;
    }

Por exemplo, uma string ANet15Amountdeve ser transformada em A Net 15 Amount. Esse regex acima também dividiria uma string camelCase, mas isso não é necessário considerar.


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

2
@ibrahimmahrir (?!^)([A-Z]|\d+)evita o primeiro espaço e não precisa de corte.
Ctwheels #

Respostas:


6

Que tal corresponder por um padrão mais básico como esse e juntar - se ao espaço.

let str = `ANet15Amount`;

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

console.log(camel);

Primeiro pensei em simplesmente, [A-Z][a-z]*|\d+mas isso iria entrar, por exemplo, ABCDefg123no A B C Defg 123qual seria diferente trabalhar para sua função atual, que se transforma em ABC Defg 123.

Ainda há uma pequena diferença. Teus transforma A1B2a A 1B 2e esta para A 1 B 2onde eu acho que este seria mais preciso, não é.


11
Brilhante, passei em todos os meus casos de teste. Eu concordo, o seu é mais preciso. Eu realmente gostei disso!
develmatik

@develmatik Ainda bem que funciona como desejado, acabei de ler sobre as diferenças de camelo PascalCase :)
Bubble Bobble

3

Basta substituir qualquer letra maiúscula [A-Z]ou qualquer sequência de dígitos \d+por um espaço mais o que acabamos de corresponder " $1". Ignoramos a primeira letra para que nenhum espaço seja adicionado no início da string resultante, adicionando um lookahead negativo no início da string (?!^):

// ...

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

Exemplo:


2

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

  • 0 ou 1 letra maiúscula diretamente seguida por 1 ou mais letras minúsculas
  • ou 1 letra maiúscula
  • ou 1 ou mais dígitos

Teste no gerador: https://regex101.com/r/uBO0P5/1


2

Eu acho que depende das convenções da string que podem aumentar a complexidade

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.