我们有一个传统的自定义地址控件。它提供了一个自由文本表单,用户可以在其中输入任何地址,甚至是部分或无效的地址;请参见屏幕截图中的绿色箭头:
以此自由文本格式输入地址是为了提供更好的用户体验;但是,必须构造地址以便进一步处理。因此,分析地址以确定街道,城镇,邮政编码,国家等。
确定这个国家似乎相当容易。我们当前的(为简化了可读性)源代码如下所示:
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;
}
这个解决方案虽然没有解决这些要求:
是否有任何人拥有完全满足一项或两项要求的智能增强(解决方案)?使用外部服务提供商进行地址验证将从可接受的答案中排除。
答案 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()
,也可以获取列表。