【问题标题】:Convert full address into individual columns将完整地址转换为单独的列
【发布时间】:2013-12-27 00:09:52
【问题描述】:

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

完整地址在单列 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);

有什么想法吗?

【问题讨论】:

  • 这是一个比您想象的更深入的问题,特别是考虑到违规地址(您是对的,子字符串不能很好地工作)和国家之间的不同格式。请参阅这个利用 Google Maps API 的问题:stackoverflow.com/questions/518210/…
  • 这会很困难,因为你没有分隔符。地址是否有模式 - 它们都是美国格式吗?他们都在纽约吗?
  • 你可能不想听到这个......但是只有 1000 行,它会更快更安全地通过你的地址运行并手动添加逗号 (,) 来分隔每个地址组件。之后使用一个简单的拆分函数
  • @VLand 完全同意这是一个一次性的过程。
  • 还有一种提取邮政编码和州代码的模式,但是“Main St New”不是街道名称而是“Main St”是“York”不是街道名称的逻辑是什么?州名,但“纽约”是?

标签: c# regex


【解决方案1】:

地址很复杂。非常复杂。它们是非常不规则和主观的东西。在几十年的过程中,物流公司花费了 数十亿 来试图理解它们。

比尝试重新发明它更好地利用其他人所做的事情。

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

使用地理编码 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"
}

现在是一些看起来很有意义的数据。也许不是您公司中的某些人认为地址是由数据的“单元”构成的,而是有意义和有用的。对于数据中的任何给定地址,您都可以自动执行此操作。

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

【讨论】:

  • Google 地理编码 API 具有以下限制:每 24 小时 2,500 个请求。 Google Maps API for Business 客户有更高的限制:每 24 小时 100,000 个请求。更多详情developers.google.com/maps/documentation/geocoding
  • 太棒了!非常感谢。
【解决方案2】:

给定以下地址:

123 Street Woodbury TN 37190

在您使用子字符串代码(4 位或 5 位)获取邮政编码后

使用仅邮政编码

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

Google Geocoding API 将返回州和城市,将其与您的地址字符串进行比较并匹配并将其删除:

你现在剩下:

123 街

你按空格分割,你得到街道号码和街道名称

给你!

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");

        }
    }
}

【讨论】:

    【解决方案3】:

    您说您有一个包含 1000 个地址的列表...但是您指定该表每天都在增长,因此您不能只是手动为每个地址添加逗号。

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

    1. 获取 ZIP,使用正则表达式或类似方法
    2. 获取状态,匹配状态表
    3. 让城市在 Cities 表中查找,如果没有,请“暂停并手动检查”
    4. 获取地址,知道第一个数字部分是门牌号

    我会检查我在支持表中找不到的项目并手动查看它们

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-30
      相关资源
      最近更新 更多