如何从字符串中提取地址组件?

时间:2014-09-30 13:48:05

标签: c# regex xamarin substring street-address

我有一个使用Xamarin的Xamarin Forms应用程序。在平台上移动以获取当前位置,然后确定当前地址。地址以字符串格式返回,并带有换行符。

地址可能如下所示:

111 Mandurah Tce
Mandurah WA 6210
Australia

The Glades
222 Mandurah Tce
Mandurah WA 6210
Australia

我有这个代码将它分解为街道地址(包括号码),郊区,州和邮政编码(不是很优雅,但它有效)

string[] lines = address.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> addyList = new List<string>(lines);
int count = addyList.Count;
string lineToSplit = addyList.ElementAt(count - 2);
string[] splitLine = lineToSplit.Split(null);
List<string> splitList = new List<string>(splitLine);

string streetAddress = addyList.ElementAt (count - 3).ToString ();
string postCode = splitList.ElementAt(2);
string state = splitList.ElementAt(1);
string suburb = splitList.ElementAt(0);

我想提取街道号码,在前面的例子中这很容易,但是最好的方法是什么,考虑到数量可能是Lot 111(只需要捕获111,而不是单词LOT),或123A或8/123 - 有时也会返回111-113

我知道我可以使用正则表达式并寻找所有可能的组合,但是在我编写任何更混乱的代码之前是否有一个优雅的内置类型解决方案(我知道上面的代码不是特别健壮) ?

4 个答案:

答案 0 :(得分:1)

正则表达式可以将匹配的部分捕获到组中。每个括号()定义一个组。

([^\d]*)(\d*)(.*)

对于"Lot 222 Mandurah Tce",这将返回以下组

组0:"Lot 222 Mandurah Tce"(输入字符串)
第1组:"Lot "
第2组:"222"
第3组:" Mandurah Tce"

说明:

[^\d]*除数字之外的任何字符的任何数字(包括0) \d*任意数字(包括0)的数字 .*任何字符的任意数字(包括0)。

string input = "Lot 222 Mandurah Tce";
Match match = Regex.Match(input, @"([^\d]*)(\d*)(.*)");
string beforeNumber = match.Groups[1].Value; // --> "Lot "
string number = match.Groups[2].Value;       // --> "222"
string afterNumber = match.Groups[3].Value;  // --> " Mandurah Tce"

如果某个群组找不到匹配项,match.Groups[i]将为该群组返回一个空字符串("")。

答案 1 :(得分:1)

这些简单的正则表达式将考虑到许多类型的地址格式,但您考虑了所有可能的变体,例如:

PO Box 123 suburb state post_code
Unit, Apt, Flat, Villa, Shop X Y street name 
7C/94 ALISON ROAD RANDWICK NSW 2031

这只是为了得到这个数字。您还必须处理所有可能类型的街道,例如Lane,Road,Place,Av,Parkway。

然后有街道类型,如:

12 Grand Ridge Road suburb_name

这可以解释为street =“Grand Ridge”和suburb =“Road suburb_name”,因为Ridge也是一种有效的街道类型。

我在这方面做了很多工作,发现大量有效的地址模式意味着简单的正则表达式无法解决大量数据的问题。

我最终开发了解析器http://search.cpan.org/~kimryan/Lingua-EN-AddressParse-1.20/lib/Lingua/EN/AddressParse.pm以解决问题。它最初是为澳大利亚地址编写的,所以应该适合你。

答案 2 :(得分:0)

您可以检查内容是否以splitLine中每个条目的编号开头。

string[] splitLine = lineToSplit.Split(addresseLine);

var streetNumber = string.empty;
foreach(var s in splitLine)
{
  //Get the first digit value
  if (Regex.IsMatch(s, @"^\d"))
  {
       streetNumber = s;
       break;
  }     
}

//以另一种方式处理空值

Console.WriteLine("My streetnumber is " + s)

答案 3 :(得分:0)

是的,我认为你必须确定哪些方法有效。

如果:

  • 它始终在地址行中,并且必须始终以数字
  • 开头
  • 该行中的任何其他内容都不能以数字开头(或者如果您知道哪些内容总是按什么顺序排列,即如果街道号码始终是第一个,则下面的代码将始终有效)
  • 你想要每个连续字符都不是空白的数字( - 和\例子对我来说是这样的)

然后就可以这么简单:

var regx = new Regex(@"(?:\s|^)\d[^\s]*");
var mtch = reg.Match(addressline);

你需要筛选并查看是否有任何假设被打破。