Search code examples
javascriptreactjsarraysobjectgeocoding

How to use map function inside an array of nested object and assigining the result to the same object?


I have array of objects with below sample data:

const data = [
{
  videoId: 'vfLdGddGwOw',
  title: 'Central Vietnamese Street Food!! Noodles from Actual Heaven!!',
  thumbnail: {
    url: 'https://i.ytimg.com/vi/vfLdGddGwOw/maxresdefault.jpg',
    width: 1280,
    height: 720
  },
  address: [
    '49/3 Trần Hưng Đạo, Sơn Phong, Hội An, Quảng Nam 56000',
    'Lê Thánh Tông street, An Phú ward, Tam Kỳ city, Quảng Nam Province'
  ],
},
{
  videoId: 'bol-_4NZjWE',
  title: 'Risky Thai Street Food!! Even Locals Don’t Eat This!!',
  thumbnail: {
    url: 'https://i.ytimg.com/vi/bol-_4NZjWE/sddefault.jpg',
    width: 640,
    height: 480
  },
  address: [
    '87 Baan Patan, T. San Pakwan, A. Hang Dong, Chiang Mai',
    'Hang Dong, Chiang Mai 50230',
    '221 Soi Hang San, Ban Waen, Hang Dong District, Chiang Mai 50230',
  ],
}

I'd like to geocode all the addresses in each object and assign the result to the object like this :

const data = [
  {
    id: 1,
    address: [
      {
        location: "49/3 Trần Hưng Đạo, Sơn Phong, Hội An, Quảng Nam 56000",
        coordinate: [15.87944, 108.335],
      },
      {
        location:
          "Lê Thánh Tông street, An Phú ward, Tam Kỳ city, Quảng Nam Province",
        coordinate: [20.95533, 107.06892],
      },
    ],
  },
  {
    id: 2,
    address: [
      {
        location: "87 Baan Patan, T. San Pakwan, A. Hang Dong, Chiang Mai",
        coordinate: [18.76794, 98.996512],
      },
      {
        location: "Hang Dong, Chiang Mai 50230",
        coordinate: [49.038833, -1.581446],
      },
      {
        location:
          "221 Soi Hang San, Ban Waen, Hang Dong District, Chiang Mai 50230",
        coordinate: [18.76794, 98.996512],
      },
    ],
  },
];

How can I do that? This what I currently have:

const geocode = async (element) => {
  const baseURL = `http://api.positionstack.com/v1/forward`;

  const params = {
    access_key: "API_KEY",
    query: element,
    limit: 1,
    output: "geojson",
    country_module: 0,
    sun_module: 0,
    timezone_module: 0,
    bbox_module: 0,
  };

  try {
    const fetchGeocode = axios.get(baseURL, { params });
    const geocodedData = fetchGeocode.data;
    element.push(geocodedData);
  } catch (error) {
    console.log(error);
  }
};

data.map((obj) => {
obj.address.map((element) => geocode(element))
}
)

When I use it, I get error: TypeError: element.push is not a function.

How can I geocode the coordinate of each address in the array of object and then push/ assign the coordinate in the same?


Solution

  • you could try:

    const geocode = async (address) => {
      const baseURL = `http://api.positionstack.com/v1/forward`;
    
      const params = {
        access_key: "API_KEY",
        query: address,
        limit: 1,
        output: "geojson",
        country_module: 0,
        sun_module: 0,
        timezone_module: 0,
        bbox_module: 0,
      };
    
      try {
        const fetchGeocode = axios.get(baseURL, { params });
        const geocodedData = fetchGeocode.data;
        return geocodedData;
      } catch (error) {
        console.log(error);
      }
    };
    
    // will map each item of the data array and search  each address at the api
    // then, will return an array of {'the_adrress_string': theResultOfTheApi}
    // i've use this return because of the example that you show the result that you want to have
    const mapGeocode = async (data) => {
       const addressesMaped = Promise.all(
         data.address.map(async(address)=> {
          const geocodeData = await geocode(address)
    
          // i don't know the return of this api, but this will return something like: 
        // {'87 Baan Patan, T. San Pakwan, A. Hang Dong, Chiang Mai': coordinate:{latitude, longitude}}
    
        // if you prefer, you could return {address: address, cordinate: ...geocodeData}
          return {
           [address]: geocodeData
          }
         }) 
    
       )
       return data
    })
    
    // this should be inside a async function 
    data = await Promise.all(
       data.map(mapGeocode)
    )