如何从自由文本地址确定国家/地区?

时间:2015-03-02 03:58:50

标签: c# street-address country

我们有一个传统的自定义地址控件。它提供了一个自由文本表单,用户可以在其中输入任何地址,甚至是部分或无效的地址;请参见屏幕截图中的绿色箭头:

example address control with free text form

以此自由文本格式输入地址是为了提供更好的用户体验;但是,必须构造地址以便进一步处理。因此,分析地址以确定街道,城镇,邮政编码,国家等。

确定这个国家似乎相当容易。我们当前的(为简化了可读性)源代码如下所示:

private static string DetermineCountryFromAddress(string fullAddress)
{
    // determine list of countries found in the full address
    string[] addressLines = fullAddress.Split(Environment.NewLine.ToCharArray());
    IList<string> countries = new List<string>();
    foreach (string addressLine in addressLines)
    {
        // check whether there's a country name hidden in this address line
        string countryName;
        if (ContainsCountry(addressLine, out countryName))
            countries.Add(countryName);
    }

    // if there has been a country found, return the country found last;
    // otherwise, return the default country (constant)
    return countries.Any() ? countries[countries.Count - 1] : DefaultCountryName;
}

为了好奇,这就是我们简化的ContainsCountry()方法的样子:

private static bool ContainsCountry(string addressLine, out string foundCountryName)
{
    // check against all countries
    foreach (string countryName in
        AllCountryNames.Where(countryName => addressLine.Contains(countryName)))
    {
        foundCountryName = countryName;
        return true;
    }

    // nothing found
    foundCountryName = null;
    return false;
}

这个解决方案虽然没有解决这些要求:

  • 国家可以在任何一行,而不仅仅是最后一行
  • 如果没有提供国家/地区,则应忽略构成街道名称一部分的国家/地区名称

是否有任何人拥有完全满足一项或两项要求的智能增强(解决方案)?使用外部服务提供商进行地址验证将从可接受的答案中排除。

1 个答案:

答案 0 :(得分:2)

根据我的说法,这是最好的解决方案

string[] addressLines = fullAddress.Split(Environment.NewLine.ToCharArray());
IList<string> countries = new List<string>();

// This will save you a bit of computation, as 90% 
// of country names will be towards the end.
for (string addressLine in addressLines.Reverse())
{
    // check whether there's a country name hidden in this address line
    string countryName;
    if (ContainsCountry(addressLine, out countryName))
        countries.Add(countryName); //Break if a country is found would further reduce the unnecessary iterations.
}

或者其他选择是使用linq

List<string> addressLines = new List<string>(Regex.Split(fullAddress, 
    Environment.NewLine));

string countryname = CountryNameList.Where(y =>
    addressLines.Any(z => z == y.countryName)).FirstOrDefault();

如果您使用ToList()代替FirstOrDefault(),也可以获取列表。