检查英国邮政编码以进行验证

时间:2019-05-24 14:57:21

标签: c#

我需要对照列表检查英国邮政编码。

英国邮政编码为标准格式,但列表仅包含我需要检查的外部部分。

该列表包含一系列外发邮政编码,以及与此外发邮政编码相关的一些数据,例如

AL     St Albans
B      Birmingham
BT     Belfast
TR     Taunton
TR21    Taunton X
TR22    Taunton Y

我的目标是当我获得邮政编码(例如B20 7TP)时,可以搜索并找到伯明翰。

任何想法?

这个问题与被称为可能答案的问题不同,但是在我的情况下,我只需要对照向外的邮政编码来检查完整的邮政编码。

2 个答案:

答案 0 :(得分:1)

如果您拥有完整的邮政编码,而只想使用外码,则删除最后三个字符并使用剩余的字符。所有邮政编码均以数字alpha-alpha模式结尾,因此删除这些字符将给出输出代码;任何不适合该模式的字符串或在删除该子字符串后未给出有效输出代码的字符串都不是有效的邮政编码。 (Source


如果您愿意接受外部(和基于Internet的)依赖关系,可以考虑使用https://postcodes.io之类的东西,尤其是该API的代码外部分。我与postcodes.io没有任何隶属关系;我刚在Google之后找到它。

根据文档,/ outcodes将返回

  • 外码
  • 东风
  • 北方人
  • 法规下的县和县
  • 代码下的地区/单一单位
  • 该守则下的行政/选举区域
  • WGS84物流
  • WGS84纬度
  • 代码中包含的国家
  • 代码中的教区/社区

作为参考,对/ outcodes / TA1的调用返回:

{
  "status": 200,
  "result": {
    "outcode": "TA1",
    "longitude": -3.10297767924529,
    "latitude": 51.0133987332761,
    "northings": 124359,
    "eastings": 322721,
    "admin_district": [
      "Taunton Deane"
    ],
    "parish": [
      "Taunton Deane, unparished area",
      "Bishop's Hull",
      "West Monkton",
      "Trull",
      "Comeytrowe"
   ],
    "admin_county": [
      "Somerset"
    ],
    "admin_ward": [
      "Taunton Halcon",
      "Bishop's Hull",
      "Taunton Lyngford",
      "Taunton Eastgate",
      "West Monkton",
      "Taunton Manor and Wilton",
      "Taunton Fairwater",
      "Taunton Killams and Mountfield",
      "Trull",
      "Comeytrowe",
      "Taunton Blackbrook and Holway"
    ],
    "country": [
      "England"
    ]
  }
}

如果您拥有完整的邮政编码,则/postcodes端点将返回更详细的信息,我将不在此处包括,但它确实将outcode和incode作为单独的字段包括在内。

我当然建议将对远程API的任何调用的结果缓存。

答案 1 :(得分:0)

从已知代码列表中构建一个正则表达式。请注意,正则表达式中已知代码的顺序很重要。您需要先使用较长的代码,然后再使用较短的代码。

private void button1_Click(object sender, EventArgs e)
{
    textBoxLog.Clear();

    var regionList = BuildList();
    var regex = BuildRegex(regionList.Keys);

    TryMatch("B20 7TP", regionList, regex);
    TryMatch("BT1 1AB", regionList, regex);
    TryMatch("TR21 1AB", regionList, regex);
    TryMatch("TR0 00", regionList, regex);
    TryMatch("XX123", regionList, regex);
}

private static IReadOnlyDictionary<string, string> BuildList()
{
    Dictionary<string, string> result = new Dictionary<string, string>();

    result.Add("AL", "St Albans");
    result.Add("B", "Birmingham");
    result.Add("BT", "Belfast");
    result.Add("TR", "Taunton");
    result.Add("TR21", "Taunton X");
    result.Add("TR22", "Taunton Y");

    return result;
}

private static Regex BuildRegex(IEnumerable<string> codes)
{
    // Sort the code by length descending so that for example TR21 is sorted before TR and is found by regex engine
    // before the shorter match
    codes = from code in codes
            orderby code.Length descending
            select code;

    // Escape the codes to be used in the regex
    codes = from code in codes
            select Regex.Escape(code);

    // create Regex Alternatives
    string codesAlternatives = string.Join("|", codes.ToArray());

    // A regex that starts with any of the codes and then has any data following
    string lRegExSource = "^(" + codesAlternatives + ").*";

    return new Regex(lRegExSource, RegexOptions.IgnoreCase | RegexOptions.Singleline);
}


/// <summary>
/// Try to match the postcode to a region
/// </summary>
private bool CheckPostCode(string postCode, out string identifiedRegion, IReadOnlyDictionary<string, string> regionList, Regex regex)
{
    // Check whether we have any match at all
    Match match = regex.Match(postCode);
    bool result = match.Success;

    if (result)
    {
        // Take region code from first match group
        // and use it in dictionary to get region name
        string regionCode = match.Groups[1].Value;
        identifiedRegion = regionList[regionCode];
    }
    else
    {
        identifiedRegion = "";
    }

    return result;
}

private void TryMatch(string code, IReadOnlyDictionary<string, string> regionList, Regex regex)
{
    string region;

    if (CheckPostCode(code, out region, regionList, regex))
    {
        AppendLog(code + ": " + region);
    }
    else
    {
        AppendLog(code + ": NO MATCH");
    }
}

private void AppendLog(string log)
{
    textBoxLog.AppendText(log + Environment.NewLine);
}

产生此输出:

B20 7TP: Birmingham
BT1 1AB: Belfast
TR21 1AB: Taunton X
TR0 00: Taunton
XX123: NO MATCH

供您参考,此处构建的正则表达式为^(TR21|TR22|AL|BT|TR|B).*