samithagun
samithagun

Reputation: 693

Get inward and outward codes from UK postal code

I'm trying to find a way to split a UK postcode from the user entry. The initial entry is validated by the below regex and it's working fine.

var regex = @"^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$";

Now I need to split the postcode into outward and inward codes so that I can send them separately to the client's ERP to get the shipping cost.

Example.

User input: DD81UN
Desired output: DD8 1UN

User input: DN551PT
Desired output: DN55 1PT

Upvotes: 3

Views: 2004

Answers (2)

degant
degant

Reputation: 4981

Only adding spaces:

As per the wikipedia entry on outward and inward codes for UK Postal codes, the rules are as follows:

  • An outward code is between two and four characters long
  • An inward code is three characters long

So if you have already extracted the code, to add spaces or split, simply add a space before the 3rd character from the end since the inward code is always 3 characters in length:

string extractedCode = "DD81UN";
extractedCode = extractedCode.Insert(extractedCode.Length - 3, " ");
// Output: DD8 1UN

Improving the Regular expression:

Based on the rules in the link you shared, here's a better version of the regex, that extracts UK Postal Codes from any text, even if they contain a space:

\b([A-PR-UWYZ](?:(?:\d{1,2}|\d[A-HJ-KSTUW])|(?:[A-HK-Y]\d(?:\d|[A-Z])?)))\s?(\d[ABD-HJLNP-UW-Z]{2})\b
  • \b represents word boundary at start and end
  • ([A-PR-UWYZ](?:(?:\d{1,2}|\d[A-HJ-KSTUW])|(?:[A-HK-Y]\d(?:\d|[A-Z])?))) is the first capturing group to match outward code which may be two to four characters in length.
    • [A-PR-UWYZ] since the first character cannot have Q, V or X
    • (?:\d{1,2}|\d[A-HJ-KSTUW]) allows formats AN, ANN and ANA and restricts characters as per the rules in the third position
    • (?:[A-HK-Y]\d(?:\d|[A-Z])?)) allows formats AAN, AANN and AANA and doesn't allow I, J and Z in the 2nd position
  • \s? matches an optional space between outward and inward codes.
  • (\d[ABD-HJLNP-UW-Z]{2}) is the second capturing group for outward codes. It allows one digit followed by two characters as per the rules.

Regex101 Demo

  • The letters Q, V and X are not used in the first position
  • The letters I,J and Z are not used in the second position.
  • The only letters to appear in the third position are A, B, C, D, E, F, G, H, J, K, S, T, U and W.
  • The second half of the postcode is always consistent numeric, alpha, alpha format and the letters C, I, K, M, O and V are never used.

If your objective is to only match and add space, match using above and replace with $1 $2 since the above regex matches outward codes in the first group and inward codes in the 2nd group.

Here's a dotnet fiddle which demonstrates the same.

string input = "sample DD81UN DN55 1PT WRONG text 123456";
Regex r = new Regex(@"\b([A-PR-UWYZ](?:(?:\d{1,2}|\d[A-HJ-KSTUW])|(?:[A-HK-Y]\d(?:\d|[A-Z])?)))\s?(\d[ABD-HJLNP-UW-Z]{2})\b");

// To add spaces between each codes
string output = r.Replace(input, "$1 $2");

// To get all codes
var results = r.Matches(output);

Upvotes: 3

Chandan Kumar
Chandan Kumar

Reputation: 4638

Try This.

namespace UKPostCodeConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string firstPostCode = "DD81UN";
            string secondPostCode = "DN551PT";
            Console.WriteLine(ParseToUkPostcode(firstPostCode));
            Console.WriteLine(ParseToUkPostcode(secondPostCode));
            Console.Read();
        }
        public static string ParseToUkPostcode(string aPostcode)
        {
            string finalPostcode = aPostcode;

            finalPostcode = finalPostcode.Replace(" ", "").Trim();
            string outWardResult = finalPostcode.Substring(0, finalPostcode.Length - 3);
            string inWardResult = finalPostcode.Substring(Math.Max(0, finalPostcode.Length - 3));
            string postCodeResult = string.Format("{0} {1}", outWardResult, inWardResult);
            finalPostcode = postCodeResult;

            return finalPostcode;
        }
    }
}

OUTPUT

enter image description here

Hope it solves your problem

Upvotes: 1

Related Questions