Dividi una stringa in lettere maiuscole o numeri


9

Stavo cercando di creare una pipe in dattiloscritto che avrebbe diviso una stringa PascalCase, ma sarebbe bello se anche questo fosse diviso anche in cifre. Vorrei anche che si dividesse in lettere maiuscole consecutive. Ho questa pipa, che funziona alla grande, tranne che funziona solo su Chrome e non su Firefox, evidentemente solo Chrome supporta i look back. Come può farlo senza guardare indietro?

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

Quindi ad esempio una stringa ANet15Amountdovrebbe essere trasformata in A Net 15 Amount. Anche questa regex sopra dividerebbe una stringa camelCase, ma non è necessario considerarla.


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

2
@ibrahimmahrir (?!^)([A-Z]|\d+)evita il primo spazio e non ha bisogno di rifiniture.
ruote dentate

Risposte:


6

Che ne dite di abbinare un modello più semplice come questo e unire lo spazio.

let str = `ANet15Amount`;

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

console.log(camel);

All'inizio ho pensato semplicemente, [A-Z][a-z]*|\d+ma questo si spezzerebbe, ad esempio, ABCDefg123in A B C Defg 123cui sarebbe diverso lavorare con la tua attuale funzione, che si trasforma in ABC Defg 123.

C'è ancora una piccola differenza. Distinti trasforma A1B2per A 1B 2e questo per A 1 B 2cui credo che questo sarebbe più esatto, non è vero.


1
Fantastico, ha superato tutti i miei casi di test. Sono d'accordo, il tuo è più preciso. Lo apprezzo molto!
develmatik,

@develmatik Sono contento che funzioni come desiderato, ho appena letto delle differenze tra Camel e PascalCase :)
bolla bobble

3

Sostituisci semplicemente una lettera maiuscola [A-Z]o una sequenza di cifre \d+con uno spazio più ciò che abbiamo appena abbinato " $1". Saltiamo la prima lettera in modo che non venga aggiunto spazio all'inizio della stringa risultante aggiungendo un lookahead negativo all'inizio della stringa (?!^):

// ...

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

Esempio:


2

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

  • 0 o 1 lettera maiuscola seguita direttamente da 1 o più lettere minuscole
  • o 1 lettera maiuscola
  • o 1 o più cifre

Test nel generatore: https://regex101.com/r/uBO0P5/1


2

Immagino che dipenda dalle convenzioni della stringa che possono aumentare la complessità

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.