在自动完成选项中解析Google地图中的address_components

Vic*_*tor 13 javascript jquery google-maps google-maps-api-3

我有以下代码来解析country选择自动完成列表的时间:

$('#spot_address').autocomplete({
  // This bit uses the geocoder to fetch address values
  source: function(request, response) {
    geocoder.geocode( {'address': request.term }, function(results, status) {
      // Get address_components
      for (var i = 0; i < results[0].address_components.length; i++)
      {
        var addr = results[0].address_components[i];
        var getCountry;
        if (addr.types[0] == 'country') 
          getCountry = addr.long_name;
      }
      response($.map(results, function(item) {
        return {
          label: item.formatted_address,
          value: item.formatted_address,
          latitude: item.geometry.location.lat(),
          longitude: item.geometry.location.lng(),
          country: getCountry
        }
      }));
    })
  },

  // This bit is executed upon selection of an address
  select: function(event, ui) {
    // Get values
    $('#spot_country').val(ui.item.country);
    $('#spot_lat').val(ui.item.latitude);
    $('#spot_lng').val(ui.item.longitude);
    var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
    marker.setPosition(location);
    map.setCenter(location);
  },

  // Changes the current marker when autocomplete dropdown list is focused
  focus: function(event, ui) {
    var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
    marker.setPosition(location);
    map.setCenter(location);
  }
});
Run Code Online (Sandbox Code Playgroud)

但是,上面的代码不起作用,并且在解析国家时,只解析自动完成的第一个结果,这对于数组很重要,results[0]因为它只获取第一个结果.

我试图把它移动到select的功能,但uiselect只包含formatted_address,longitudelatitude,但不是address_components.

country选择自动填充列表项时,我该怎么做才能发送正确的内容?

非常感谢.

Wil*_*ken 75

一般解决方案

var address_components = results[0].address_components;
var components={}; 
jQuery.each(address_components, function(k,v1) {jQuery.each(v1.types, function(k2, v2){components[v2]=v1.long_name});});
Run Code Online (Sandbox Code Playgroud)

现在components看起来像这样:

street_number: "1100", 
route: "E Hector St", 
locality: "Conshohocken", 
political: "United States", 
administrative_area_level_3: "Whitemarsh"…
administrative_area_level_1: "Pennsylvania"
administrative_area_level_2: "Montgomery"
administrative_area_level_3: "Whitemarsh"
country: "United States"
locality: "Conshohocken"
political: "United States"
postal_code: "19428"
route: "E Hector St"
street_number: "1100"
Run Code Online (Sandbox Code Playgroud)

你可以这样查询:

components.country
Run Code Online (Sandbox Code Playgroud)

  • +1,简单但在大多数情况下很有用.请注意,某些信息可能会在此过程中丢失(例如,当您有两种类型的组件['country','political']和['locality','political']时,政治会被覆盖) (4认同)

Vic*_*tor 7

我在这里再次回答我自己的问题.以下是完整的工作代码:

$('#spot_address').autocomplete({
  // This bit uses the geocoder to fetch address values
  source: function(request, response) {
    geocoder.geocode( {'address': request.term }, function(results, status) {
      response($.map(results, function(item) {
          // Get address_components
          for (var i = 0; i < item.address_components.length; i++)
          {
            var addr = item.address_components[i];
            var getCountry;
            if (addr.types[0] == 'country') 
              getCountry = addr.long_name;
          }
        return {
          label: item.formatted_address,
          value: item.formatted_address,
          latitude: item.geometry.location.lat(),
          longitude: item.geometry.location.lng(),
          country: getCountry
        }
      }));
    })
  },

  // This bit is executed upon selection of an address
  select: function(event, ui) {
    // Get values
    $('#spot_country').val(ui.item.country);
    $('#spot_lat').val(ui.item.latitude);
    $('#spot_lng').val(ui.item.longitude);
    var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
    marker.setPosition(location);
    map.setCenter(location);
  },

  // Changes the current marker when autocomplete dropdown list is focused
  focus: function(event, ui) {
    var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
    marker.setPosition(location);
    map.setCenter(location);
  }
});
Run Code Online (Sandbox Code Playgroud)


Yom*_* S. 7

这是一个 ES6 和 jQuery-less 解决方案(基于William Entriken 的帖子),利用本机reduce函数和解构赋值语法将对象的属性解包为不同的变量:

const address = address_components.reduce((seed, { long_name, types }) => {
  types.forEach(t => {
    seed[t] = long_name;
  });

  return seed;
}, {});
Run Code Online (Sandbox Code Playgroud)

或者,单线版本(物有所值):

const address = address_components.reduce((seed, { long_name, types }) => (types.forEach(t => seed[t] = long_name), seed), {});
Run Code Online (Sandbox Code Playgroud)

然后你可以使用它:

address.street_number
address.city
Run Code Online (Sandbox Code Playgroud)


Chr*_*ich 5

在@Full Decent的答案中详细说明了lodash的一个版本:

_.each(address_components, function(k, v1) {
    _.each(address_components[v1].types, function(k2, v2){
        components[address_components[v1].types[v2]] = address_components[v1].long_name
    });
});
Run Code Online (Sandbox Code Playgroud)


Ale*_*sin 5

这是我的打字稿解决方案

interface AddressComponent {
  long_name: string;
  short_name: string;
  types: Array<string>;
}

interface Address {
  street_number?: string;
  street_name?: string;
  city?: string;
  state?: string;
  country?: string;
  postal_code?: string;
}

export class GoogleAddressParser {
  private address: Address = {};

  constructor(private address_components: Array<AddressComponent>) {
    this.parseAddress();
  }

  private parseAddress() {
    if (!Array.isArray(this.address_components)) {
      throw Error('Address Components is not an array');
    }

    if (!this.address_components.length) {
      throw Error('Address Components is empty');
    }

    for (let i = 0; i < this.address_components.length; i++) {
      const component: AddressComponent = this.address_components[i];

      if (this.isStreetNumber(component)) {
        this.address.street_number = component.long_name;
      }

      if (this.isStreetName(component)) {
        this.address.street_name = component.long_name;
      }

      if (this.isCity(component)) {
        this.address.city = component.long_name;
      }

      if (this.isCountry(component)) {
        this.address.country = component.long_name;
      }

      if  (this.isState(component)) {
        this.address.state = component.long_name;
      }

      if (this.isPostalCode(component)) {
        this.address.postal_code = component.long_name;
      }
    }
  }

  private isStreetNumber(component: AddressComponent): boolean {
    return component.types.includes('street_number');
  }

  private isStreetName(component: AddressComponent): boolean {
    return component.types.includes('route');
  }

  private isCity(component): boolean {
    return component.types.includes('locality');
  }

  private isState(component): boolean {
    return component.types.includes('administrative_area_level_1');
  }

  private isCountry(component): boolean {
    return component.types.includes('country');
  }

  private isPostalCode(component): boolean {
    return component.types.includes('postal_code');
  }

  result(): Address {
    return this.address;
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

const address = new GoogleAddressParser(results[0].address_components).result();
Run Code Online (Sandbox Code Playgroud)


小智 5

这里我自己做了一个解决方案,因为我想获取城市名称,并且可能有不止一种格式,例如,某些地区的城市名称可以在以下名称下

 (locality, sublocality , sublocality_level_1, sublocality_level_2, sublocality_level_3
 or sublocality_level_4)
Run Code Online (Sandbox Code Playgroud)

所以我做了这个功能

getAddressObject(address_components) {
  var ShouldBeComponent = {
    home: ["street_number"],
    postal_code: ["postal_code"],
    street: ["street_address", "route"],
    region: [
      "administrative_area_level_1",
      "administrative_area_level_2",
      "administrative_area_level_3",
      "administrative_area_level_4",
      "administrative_area_level_5"
    ],
    city: [
      "locality",
      "sublocality",
      "sublocality_level_1",
      "sublocality_level_2",
      "sublocality_level_3",
      "sublocality_level_4"
    ],
    country: ["country"]
  };

  var address = {
    home: "",
    postal_code: "",
    street: "",
    region: "",
    city: "",
    country: ""
  };
  address_components.forEach(component => {
    for (var shouldBe in ShouldBeComponent) {
      if (ShouldBeComponent[shouldBe].indexOf(component.types[0]) !== -1) {
        address[shouldBe] = component.long_name;
      }
    }
  });
  console.log(address);
  return address;
}
Run Code Online (Sandbox Code Playgroud)