Remove codes from city names using regex

Viewed 188

I need to find a regex that is able to sanitize the input by removing city codes and keeping the name of the cities.

...
1105 AZ Amsterdam
AB25 2ZN Aberdeen
SY3 8XQ Shrewsbury
2XU Edinburh
NP20 2UB Newport
T4000 DGI San Miguel de Tucumán
BL9 7TD Lancashire
M13 9WL Manchester
L1H 7K4 Oshawa
...

Expected output:

...
Amsterdam
Aberdeen
Shrewsbury
Edinburgh
Newport
San Miguel de Tucumán
Lancashire
Manchester
Oshawa
...

I tried r"([0-9-]+\b)|([A-Z]+[0-9-]+\b)" but it takes only first codes

2 Answers

The difficulty here is that you want to match a sequence of upper case letters, digits or spaces, but you don't want to match only a space, and probably you don't want to match anything that does not contain any digits.

Although there may be a simpler form, one thing that would work would be to insist on there being a digit, with any number of the other characters both before and after it.

The pattern should also start and finish on a word boundary, so that e.g. it does not strip off the capital letter at the start of the following word.

import re

re.sub(r'\b[A-Z\d ]*\d[A-Z\d ]*\b', '', address)

Output for the examples in the question:

Amsterdam
Aberdeen
Shrewsbury
Edinburh
Newport
San Miguel de Tucumán
Lancashire
Manchester
Oshawa

Output for 20007 Washington mentioned elsewhere in a comment:

Washington

Inventing an example with the code at the end, namely:

Some other address SW1A 1AA

It gives:

Some other address

Note: if some of the codes do not contain any digits, then maybe what you could do is replace the \d in the middle with (\d|[A-Z]{2}) so that it is also sufficient if it contains two upper case letters together. You would not want to treat a single upper case letter as a code, e.g. A Coruña.

The first step is to create a rule to specify what constitutes a valid city name, to be extracted, or what constitutes strings that are not part of the city name, to be converted to empty strings. I will do the latter, mainly because of the complexity introduced by having to match Unicode characters (e.g., "Tucumán").

It appears that the part at the beginning that is to be removed consists of one or more substrings, each comprised of two or more capital letters or digits, followed by one or more spaces. We can match that with the following regular expression.

r'^(?:[A-Z0-9]{2,} +)+'

Start your engine!

The SUBSTITUTION box at the link is empty.

Python's regex engine performs the following operations.

^                 : match beginnning of the string
(?:               : begin a non-capture group
  [A-Z0-9]{2,} +  : match 2+ uppercase letters or digits followed by 1+ spaces
)                 : end non-capture group
+                 : execute non-capture group 1+ times
Related