将完整地址转换为单个列

时间:2013-12-26 15:19:13

标签: c# regex

我有一个加载到oracle表中的1000个地址的列表。

完整地址位于单列CompleteAddress Varchar(1000)

示例数据:

12003 Main St New York NY 00991
123 ANYWHERE BLVD ABINGDON MD 21009

我需要将所有地址拆分为Street No + Street Name,City,State和Zip(有时是zip5 + zip4)

数据中没有逗号或斜杠。如何拆分地址?如果这很重要,我在C#工作。 RegEx是适当的方法吗?

到目前为止,我尝试使用SubString,但我认为这样做不会很好。

string zipcode = completeAddress.Substring(completeAddress.Length - 5, 5);
string mystate = completeAddress.Substring(completeAddress.Length - 8, 2);

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

地址很复杂。非常复杂。它们是高度不规则和主观的东西。物流公司在 years 的过程中花了数十亿美元试图理解它们。

更好地利用别人的所作所为,而不是试图重新发明它。

您拥有的数据实际上非常有意义。它只是没有“感觉”非常有意义。企业喜欢将他们的地址数据分成许多小块,但为什么呢?所有这些小碎片意味着什么?为什么他们需要彼此区分?您拥有的数据是“地址”。保留它,但添加它。利用现有信息推断更多信息。

使用地理编码API(Google?Bing?其他一些服务?价格等会有所不同)来搜索您拥有的数据并带回更强类型的数据。与您拥有的东西一起存放。例如,你有这个:

12003 Main St New York NY 00991

所以你在这里提出要求:

http://maps.googleapis.com/maps/api/geocode/json?address=12003+Main+St+New+York+NY+00991&sensor=false

你回来了:

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "D R Main Street",
               "short_name" : "D R Main Street",
               "types" : [ "point_of_interest", "establishment" ]
            },
            {
               "long_name" : "5",
               "short_name" : "5",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "West 31st Street",
               "short_name" : "W 31st St",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Midtown",
               "short_name" : "Midtown",
               "types" : [ "neighborhood", "political" ]
            },
            {
               "long_name" : "Manhattan",
               "short_name" : "Manhattan",
               "types" : [ "sublocality", "political" ]
            },
            {
               "long_name" : "New York",
               "short_name" : "New York",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "New York",
               "short_name" : "New York",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "New York",
               "short_name" : "NY",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "10001",
               "short_name" : "10001",
               "types" : [ "postal_code" ]
            },
            {
               "long_name" : "4414",
               "short_name" : "4414",
               "types" : []
            }
         ],
         "formatted_address" : "D R Main Street, 5 West 31st Street, New York, NY 10001, USA",
         "geometry" : {
            "location" : {
               "lat" : 40.7468529,
               "lng" : -73.9865046
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.7482018802915,
                  "lng" : -73.98515561970851
               },
               "southwest" : {
                  "lat" : 40.7455039197085,
                  "lng" : -73.98785358029151
               }
            }
         },
         "partial_match" : true,
         "types" : [ "point_of_interest", "establishment" ]
      }
   ],
   "status" : "OK"
}

现在 是一些有意义的数据。也许不是贵公司某人所认为的数据的“单位”,而是有意义和有用的。对于数据中的任何给定地址,您可以自动执行此操作。

让用户以他们所知的方式输入他们的地址。将该主观地址存储为用户输入的版本。对其进行地理编码以获得更多结构化数据以与其一起存储。

答案 1 :(得分:3)

鉴于以下地址:

123 Street Woodbury TN 37190

使用子字符串代码获取邮政编码后,使用4位数或5位

使用仅限邮政编码

请求谷歌地图地理编码api
[http://maps.googleapis.com/maps/api/geocode/json?address=37190&sensor=true][1]

Google地理编码API将返回,州和城市,比较&将它与您的地址字符串匹配并将其删除:

你现在离开了:

123 Street

您按空格分割,获得街道号码和街道名称

你走了!

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        public class GoogleGeoCodeResponse
        {

            public string status { get; set; }
            public results[] results { get; set; }

        }

        public class results
        {
            public string formatted_address { get; set; }
            public geometry geometry { get; set; }
            public string[] types { get; set; }
            public address_component[] address_components { get; set; }
        }

        public class geometry
        {
            public string location_type { get; set; }
            public location location { get; set; }
        }

        public class location
        {
            public string lat { get; set; }
            public string lng { get; set; }
        }

        public class address_component
        {
            public string long_name { get; set; }
            public string short_name { get; set; }
            public string[] types { get; set; }
        }

        private class Address {
            public string StreetNumber { get; set; }
            public string StreeName { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string ZipCode { get; set; }
        }



        private static Address ParseAddress(string addressStr) {
            var address = new Address();
            address.ZipCode = addressStr.Split(' ').Last();
            var googleStr = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=" + address.ZipCode;
            var result = new System.Net.WebClient().DownloadString(googleStr);
            var resObj = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(result);

            address.City = resObj.results[0].address_components[1].long_name;
            address.State = resObj.results[0].address_components[2].short_name;
            addressStr = addressStr.Replace(" " + address.City, "").Replace(" " + address.State, "").Replace(" " + address.ZipCode, "");

            address.StreetNumber = addressStr.Split(' ')[0];
            address.StreeName = addressStr.Split(' ')[1];

            return address;
        }

        static void Main(string[] args)
        {

           var address = ParseAddress("123 Street Woodbury TN 37190");

        }
    }
}

答案 2 :(得分:1)

你说你有一个包含1000个地址的列表......但是你指定了这个表每天都在增长,所以你不能只手动为每个地址添加逗号。

如果您无法对其进行地理编码,我想我会创建其他支持表/列表(US cities, US States)并尝试从右侧开始隔离组件。

  1. 获取ZIP,使用正则表达式或类似的
  2. 获取状态,与状态表匹配
  3. 让城市查看城市表,如果没有“暂停并手动检查”
  4. 获取地址,知道第一个数字部分是街道号
  5. 我会检查我在支持表中找不到的项目并手动查看