What is the best regex for a mix of capitalised words and symbols?

Viewed 46

I'm trying to organise the following list: list of gaming genre

I want to separate the concatenated words, but seems like they won't take the uppercase words that represents acronyms (e.g. PVP, MMORPG, MOBA, DeFi) properly.

Currently, my regex code is as follows:

re.sub(r"(\w)([A-Z])", r"\1 \2", ele) for ele in genre_list

As you can see below, it sometimes it works and sometimes it doesn't:

['Collectible Open-World Virtual-World', 'Breeding Card PV P', 'Auto-Battler Breeding Strategy', 'Minigame Open-World Virtual-World', 'Action Simulation Sports', 'Adventure MM OStrategy', 'Adventure Casual Puzzle', 'Sports', 'Collectible Sci-Fi Virtual-World', 'Battle-Royalee Sports MO BA', 'Action PV PShooter', 'P VP Sci-Fi Tower-Defense', 'Action Battle-Royale', 'P VP Sci-Fi Shooter', 'Breeding Collectible Mining', 'Collectible De Fie Sports', 'Action Adventure Shooter', 'City-Building Collectible Simulation', 'Action Strategy', 'Adventure Open-World', 'Breeding Racing Sports', 'Open-World Virtual-World', 'Collectible Idle', 'Action Adventure', 'Card Collectible PV P', 'Battle-Royale Fantasy MO BA', 'City-Building', 'Building MM OStrategy', 'Adventure MM OR PG', 'Action Adventure Idle', 'M OB AR PG Strategy', 'M MO RP GStrategy', 'Card Collectible Idle', 'Open-World PV PR PG', 'De Fi MM OSpace', 'Collectible', 'Card Collectible PV P', 'Auto-Battler De Fi RP G', 'Adventure MM OOpen-World', 'Collectible Open-World Virtual-World', 'Collectible Idle RP G', 'Card Collectible PV P', 'Action Adventure PV P', 'Sci-Fi Shooter Survival', 'Action Strategy', 'Arcade Minigame', 'Breeding PV PRacing', 'M OB AP VP', 'Action Sports', 'P VP Space Turn-based', 'M MO Strategy Tower-Defense']

Can you help me which regex would do best on this? Or regex just doesn't work for this list? Thanks!

2 Answers

Editing based on the comments: You just need to add a '+' after the [A-Z] i.e. r"(\w)([A-Z]+)". This will match 1 or more capital letters.

It is difficult because you have ALLCAPS words that may be glued. If you have such a list, it is solvable.

Here is a code you can use and enhance to get even better output precision:

import re
l = ['Collectible Open-World Virtual-World', 'Breeding Card PV P', 'Auto-Battler Breeding Strategy', 'Minigame Open-World Virtual-World', 'Action Simulation Sports', 'Adventure MM OStrategy', 'Adventure Casual Puzzle', 'Sports', 'Collectible Sci-Fi Virtual-World', 'Battle-Royalee Sports MO BA', 'Action PV PShooter', 'P VP Sci-Fi Tower-Defense', 'Action Battle-Royale', 'P VP Sci-Fi Shooter', 'Breeding Collectible Mining', 'Collectible De Fie Sports', 'Action Adventure Shooter', 'City-Building Collectible Simulation', 'Action Strategy', 'Adventure Open-World', 'Breeding Racing Sports', 'Open-World Virtual-World', 'Collectible Idle', 'Action Adventure', 'Card Collectible PV P', 'Battle-Royale Fantasy MO BA', 'City-Building', 'Building MM OStrategy', 'Adventure MM OR PG', 'Action Adventure Idle', 'M OB AR PG Strategy', 'M MO RP GStrategy', 'Card Collectible Idle', 'Open-World PV PR PG', 'De Fi MM OSpace', 'Collectible', 'Card Collectible PV P', 'Auto-Battler De Fi RP G', 'Adventure MM OOpen-World', 'Collectible Open-World Virtual-World', 'Collectible Idle RP G', 'Card Collectible PV P', 'Action Adventure PV P', 'Sci-Fi Shooter Survival', 'Action Strategy', 'Arcade Minigame', 'Breeding PV PRacing', 'M OB AP VP', 'Action Sports', 'P VP Space Turn-based', 'M MO Strategy Tower-Defense']
l = [''.join(s.split()) for s in l]
allcaps = ['RPG', 'MOBA', 'PVP', 'MMO']
rx_1 = re.compile(r'[a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z])')
rx_2 = re.compile( fr"\b(?:{r'|'.join(allcaps)})(?=[A-Za-z])" )
rx_3 = re.compile( fr"(?<=[A-Za-z])(?:{r'|'.join(allcaps)})\b" )
for s in l:
    print( r'{} => {}'.format(s, rx_3.sub(r" \g<0>", rx_2.sub(r"\g<0> ", rx_1.sub(r"\g<0> ", s)))) )

See the Python demo. Output:

CollectibleOpen-WorldVirtual-World => Collectible Open-World Virtual-World
BreedingCardPVP => Breeding Card PVP
Auto-BattlerBreedingStrategy => Auto-Battler Breeding Strategy
MinigameOpen-WorldVirtual-World => Minigame Open-World Virtual-World
ActionSimulationSports => Action Simulation Sports
AdventureMMOStrategy => Adventure MMO Strategy
AdventureCasualPuzzle => Adventure Casual Puzzle
Sports => Sports
CollectibleSci-FiVirtual-World => Collectible Sci-Fi Virtual-World
Battle-RoyaleeSportsMOBA => Battle-Royalee Sports MOBA
ActionPVPShooter => Action PVP Shooter
PVPSci-FiTower-Defense => PVP Sci-Fi Tower-Defense
ActionBattle-Royale => Action Battle-Royale
PVPSci-FiShooter => PVP Sci-Fi Shooter
BreedingCollectibleMining => Breeding Collectible Mining
CollectibleDeFieSports => Collectible De Fie Sports
ActionAdventureShooter => Action Adventure Shooter
City-BuildingCollectibleSimulation => City-Building Collectible Simulation
ActionStrategy => Action Strategy
AdventureOpen-World => Adventure Open-World
BreedingRacingSports => Breeding Racing Sports
Open-WorldVirtual-World => Open-World Virtual-World
CollectibleIdle => Collectible Idle
ActionAdventure => Action Adventure
CardCollectiblePVP => Card Collectible PVP
Battle-RoyaleFantasyMOBA => Battle-Royale Fantasy MOBA
City-Building => City-Building
BuildingMMOStrategy => Building MMO Strategy
AdventureMMORPG => Adventure MMO RPG
ActionAdventureIdle => Action Adventure Idle
MOBARPGStrategy => MOBA RPG Strategy
MMORPGStrategy => MMO RPG Strategy
CardCollectibleIdle => Card Collectible Idle
Open-WorldPVPRPG => Open-World PVP RPG
DeFiMMOSpace => De Fi MMO Space
Collectible => Collectible
CardCollectiblePVP => Card Collectible PVP
Auto-BattlerDeFiRPG => Auto-Battler De Fi RPG
AdventureMMOOpen-World => Adventure MMO Open-World
CollectibleOpen-WorldVirtual-World => Collectible Open-World Virtual-World
CollectibleIdleRPG => Collectible Idle RPG
CardCollectiblePVP => Card Collectible PVP
ActionAdventurePVP => Action Adventure PVP
Sci-FiShooterSurvival => Sci-Fi Shooter Survival
ActionStrategy => Action Strategy
ArcadeMinigame => Arcade Minigame
BreedingPVPRacing => Breeding PVP Racing
MOBAPVP => MOBA PVP
ActionSports => Action Sports
PVPSpaceTurn-based => PVP Space Turn-based
MMOStrategyTower-Defense => MMO Strategy Tower-Defense

The [a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]) regex (see its demo) matches

  • [a-z](?=[A-Z]) - a lowercase letter that is immediately followed with an uppercase letter
  • | - or
  • [A-Z](?=[A-Z][a-z]) - an uppercase letter followed with an uppercase letter and a lowercase letter.

We add a space after these matches.

rx_2 and rx_3 regexes are built from the list of ALLCAPS words and add a space on the left or right, depending on which side another letter appears.

Related