Podziel ciąg na wielką literę lub cyfry

9

Próbowałem utworzyć potok w maszynie do pisania, który podzieliłby łańcuch PascalCase, ale byłoby miło, gdyby to również podzieliło się na cyfry. Chciałbym również, aby dzieliła się na kolejne duże litery. Mam ten potok, który działa świetnie, z tym że działa tylko w Chrome, a nie w Firefoxie, najwyraźniej tylko Chrome obsługuje przeglądanie wstecz. Jak można to osiągnąć bez odwrotu?

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

Na przykład ciąg ANet15Amountpowinien zostać przekształcony w A Net 15 Amount. Powyższe wyrażenie regularne również podzieli ciąg camelCase, ale nie jest to konieczne do rozważenia.

develmatik
źródło
.replace(/([A-Z]|\d+)/g, " $1").trim();
ibrahim mahrir
2
@ibrahimmahrir (?!^)([A-Z]|\d+)unika pierwszego miejsca i nie wymaga przycinania.
ctwheels

Odpowiedzi:

6

Co powiesz na dopasowanie bardziej prostym wzorem takim jak ten i połączenie ze spacją.

let str = `ANet15Amount`;

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

console.log(camel);

Najpierw myślałem po prostu [A-Z][a-z]*|\d+, ale to złamie np ABCDefg123w A B C Defg 123której byłaby inna roboczego do bieżącej funkcji, które zmieniają się ABC Defg 123.

Nadal jest mała różnica. Twoja przemienia A1B2się w A 1B 2tę i A 1 B 2tam, gdzie myślę, że ta będzie bardziej dokładna, prawda?

chwiejąca się bańka
źródło
1
Świetnie, przeszedłem wszystkie moje testy. Zgadzam się, twój jest dokładniejszy. Bardzo to doceniam!
develmatik
@develmatik Cieszę się, że działa zgodnie z życzeniem, właśnie przeczytałem o różnicach między Camel a PascalCase :)
bobble bubble
3

Po prostu zamień dowolną wielką literę [A-Z]lub sekwencję cyfr \d+spacją plus to, co właśnie dopasowaliśmy " $1". Pomijamy pierwszą literę, aby żadne spacje nie były dodawane na początku wynikowego ciągu, dodając ujemny wynik na początku łańcucha (?!^):

// ...

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

Przykład:

ibrahim mahrir
źródło
2

Próbować [A-Z]?[a-z]+|[A-Z]|[0-9]+

  • 0 lub 1 wielka litera bezpośrednio po niej 1 lub więcej małych liter
  • lub 1 duża litera
  • lub 1 lub więcej cyfr

Test w generatorze: https://regex101.com/r/uBO0P5/1

Tony
źródło
2

Myślę, że to zależy od konwencji ciągu, co może zwiększyć złożoność

// 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
źródło