How to combine two array of objects where key name is different but the corresponding value is same?

Viewed 87
const cafes = [
  {
    name: "Bazaar Cafe",
    place_id: "kjk234g4gcvfx8usg1l33pi",
  },
  {
    name: "Ashley's Cafe",
    place_id: "12hydbdf76sljfts87sbfis",
  },
  {
    name: "Avenue Cafe",
    place_id: "skjd86svvfdrsv55svbvf3f",
  },
  {
    name: "Hi-Lo Cafe",
    place_id: "mjdhgetr4pojfyts22fzfsh",
  },
  {
    name: "California Chicken Cafe",
    place_id: "12hydbdf76sljfts87sbfis",
  },
  {
    name: "Avenue Bakery Cafe",
    place_id: "jahgde7wgdiau8ewsahgosd",
  },
  {
    name: "Philz Coffee",
    place_id: "urhw3837ehalod7w02b7835",
  },
];

const places = [
  {
    id: "jahgde7wgdiau8ewsahgosd",
    street_no: "60H",
    locality: "Solomos Island Road",
    postal_code: "20688",
    lat: "36.7783 N",
    long: "119.4179 W",
  },
  {
    id: "12hydbdf76sljfts87sbfis",
    street_no: "1B",
    locality: "Macarthur Blvd",
    postal_code: "20619",
    lat: "38.1781 N",
    long: "118.4171 W",
  },
  {
    id: "kjk234g4gcvfx8usg1l33pi",
    street_no: "45250",
    locality: "Worth Avenue, Unit A",
    postal_code: "20619",
    lat: "36.1152",
    long: "117.521",
  },
  {
    id: "saswe3s6yydtdr52hsd72yst",
    street_no: "1X",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "36.7783",
    long: "119.4179",
  },
  {
    id: "skjd86svvfdrsv55svbvf3f",
    street_no: "7S",
    locality: "Three Notch Road",
    postal_code: "20619",
    lat: "36.83",
    long: "119.6",
  },
  {
    id: "mjdhgetr4pojfyts22fzfsh",
    street_no: "22803",
    locality: "Gunston Dr Lexington Park",
    postal_code: "20688",
    lat: "35.7788",
    long: "119.979",
  },
  {
    id: "urhw3837ehalod7w02b7835",
    street_no: "225",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "35.77813",
    long: "119.41791",
  },
];

I want final combined array to be like the following -

finalArr = [
  {
    id: "kjk234g4gcvfx8usg1l33pi",
    street_no: "45250",
    locality: "Worth Avenue, Unit A",
    postal_code: "20619",
    lat: "36.1152",
    long: "117.521",
    name: "Bazaar Cafe"
  },
  {
    id: "12hydbdf76sljfts87sbfis",
    street_no: "1B",
    locality: "Macarthur Blvd",
    postal_code: "20619",
    lat: "38.1781 N",
    long: "118.4171 W",
    name: "Ashley's Cafe"
  },
  {
    id: "12hydbdf76sljfts87sbfis",
    street_no: "1B",
    locality: "Macarthur Blvd",
    postal_code: "20619",
    lat: "38.1781 N",
    long: "118.4171 W",
    name: "California Chicken Cafe"
  },
  {
    id: "skjd86svvfdrsv55svbvf3f",
    street_no: "7S",
    locality: "Three Notch Road",
    postal_code: "20619",
    lat: "36.83",
    long: "119.6",
    name: "Avenue Cafe"
  },
  {
    id: "mjdhgetr4pojfyts22fzfsh",
    street_no: "22803",
    locality: "Gunston Dr Lexington Park",
    postal_code: "20688",
    lat: "35.7788",
    long: "119.979",
    name: "Hi-Lo Cafe"
  },
  {
    id: "jahgde7wgdiau8ewsahgosd",
    street_no: "60H",
    locality: "Solomos Island Road",
    postal_code: "20688",
    lat: "36.7783 N",
    long: "119.4179 W",
    name: "Avenue Bakery Cafe"
  }, 
  {
    id: "urhw3837ehalod7w02b7835",
    street_no: "225",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "35.77813",
    long: "119.41791",
    name: "Philz Coffee"
  }
];

I have tried to implement it like this but only getting the last object of the final array -

function combineById (cafes, places) {
  const finalArr = [];
  const wholeObj = {};
  const set = new Set();

  for (const cafe of cafes) { 
    let cafeId = cafe.place_id;
    let cafeName = cafe.name;
    for (const place of places) {
      if (cafeId === place.id && !set.has(cafeId)) {
        set.add(cafeId);
        wholeObj.id = place.id;
        wholeObj.streetNo = place.street_no;
        wholeObj.locality = place.locality;
        wholeObj.postalCode = place.postal_code;
        wholeObj.lat = place.lat;
        wholeObj.long = place.long;
        wholeObj.name = cafeName;
      }
    }
    finalArr.push(wholeObj);
  }
  return finalArr;
}

const resultArr = combineById(cafes, places);
console.log(resultArr);

I am trying to implement a search function that will accept two arguments i.e., this final array and a search term. So far the search function is working fine on the cafes array but I am having difficulty to combine the places and cafes array, combineById function returning only the last combined object result of the final array. I want all the combination of objects in the final array so that later on I can directly call final array for further manipulation. Please help me to find out a solution. Thank you.

5 Answers

const cafes = [
  {
    name: "Bazaar Cafe",
    place_id: "kjk234g4gcvfx8usg1l33pi",
  },
  {
    name: "Ashley's Cafe",
    place_id: "12hydbdf76sljfts87sbfis",
  },
  {
    name: "Avenue Cafe",
    place_id: "skjd86svvfdrsv55svbvf3f",
  },
  {
    name: "Hi-Lo Cafe",
    place_id: "mjdhgetr4pojfyts22fzfsh",
  },
  {
    name: "California Chicken Cafe",
    place_id: "12hydbdf76sljfts87sbfis",
  },
  {
    name: "Avenue Bakery Cafe",
    place_id: "jahgde7wgdiau8ewsahgosd",
  },
  {
    name: "Philz Coffee",
    place_id: "urhw3837ehalod7w02b7835",
  },
];

const places = [
  {
    id: "jahgde7wgdiau8ewsahgosd",
    street_no: "60H",
    locality: "Solomos Island Road",
    postal_code: "20688",
    lat: "36.7783 N",
    long: "119.4179 W",
  },
  {
    id: "12hydbdf76sljfts87sbfis",
    street_no: "1B",
    locality: "Macarthur Blvd",
    postal_code: "20619",
    lat: "38.1781 N",
    long: "118.4171 W",
  },
  {
    id: "kjk234g4gcvfx8usg1l33pi",
    street_no: "45250",
    locality: "Worth Avenue, Unit A",
    postal_code: "20619",
    lat: "36.1152",
    long: "117.521",
  },
  {
    id: "saswe3s6yydtdr52hsd72yst",
    street_no: "1X",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "36.7783",
    long: "119.4179",
  },
  {
    id: "skjd86svvfdrsv55svbvf3f",
    street_no: "7S",
    locality: "Three Notch Road",
    postal_code: "20619",
    lat: "36.83",
    long: "119.6",
  },
  {
    id: "mjdhgetr4pojfyts22fzfsh",
    street_no: "22803",
    locality: "Gunston Dr Lexington Park",
    postal_code: "20688",
    lat: "35.7788",
    long: "119.979",
  },
  {
    id: "urhw3837ehalod7w02b7835",
    street_no: "225",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "35.77813",
    long: "119.41791",
  },
];

let transformed = places.reduce((result,place)=>{
  let cafe = cafes.find(c=>c.place_id===place.id);
  cafe && result.push({...place,name: cafe.name});
  return result;
},[]);

console.log(JSON.stringify(transformed, null,2));

To avoid multiple (and potentially slow) finds, I'd create a Map of places first.

function combine(cafes, places) {

  // create Map of places with id as key
  const placesMap = new Map();
  places.forEach(place => {
    placesMap.set(place.id, place);
  });
  
  // combine each cafe with matching place
  const cafesWithPlaces = cafes.map(cafe => {
    let place = placesMap.get(cafe.place_id);
    
    // handle no matching place
    if (place === undefined) { return; }
    
    let combined = Object.assign({}, place);
    combined.name = cafe.name;
    return combined;
  });
  
  return cafesWithPlaces;
}

const cafes = [
  {
    name: "Bazaar Cafe",
    place_id: "kjk234g4gcvfx8usg1l33pi"
  },
  {
    name: "Ashley's Cafe",
    place_id: "12hydbdf76sljfts87sbfis"
  },
  {
    name: "Avenue Cafe",
    place_id: "skjd86svvfdrsv55svbvf3f"
  },
  {
    name: "Hi-Lo Cafe",
    place_id: "mjdhgetr4pojfyts22fzfsh"
  },
  {
    name: "California Chicken Cafe",
    place_id: "12hydbdf76sljfts87sbfis"
  },
  {
    name: "Avenue Bakery Cafe",
    place_id: "jahgde7wgdiau8ewsahgosd"
  },
  {
    name: "Philz Coffee",
    place_id: "urhw3837ehalod7w02b7835"
  }
];

const places = [
  {
    id: "jahgde7wgdiau8ewsahgosd",
    street_no: "60H",
    locality: "Solomos Island Road",
    postal_code: "20688",
    lat: "36.7783 N",
    long: "119.4179 W"
  },
  {
    id: "12hydbdf76sljfts87sbfis",
    street_no: "1B",
    locality: "Macarthur Blvd",
    postal_code: "20619",
    lat: "38.1781 N",
    long: "118.4171 W"
  },
  {
    id: "kjk234g4gcvfx8usg1l33pi",
    street_no: "45250",
    locality: "Worth Avenue, Unit A",
    postal_code: "20619",
    lat: "36.1152",
    long: "117.521"
  },
  {
    id: "saswe3s6yydtdr52hsd72yst",
    street_no: "1X",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "36.7783",
    long: "119.4179"
  },
  {
    id: "skjd86svvfdrsv55svbvf3f",
    street_no: "7S",
    locality: "Three Notch Road",
    postal_code: "20619",
    lat: "36.83",
    long: "119.6"
  },
  {
    id: "mjdhgetr4pojfyts22fzfsh",
    street_no: "22803",
    locality: "Gunston Dr Lexington Park",
    postal_code: "20688",
    lat: "35.7788",
    long: "119.979"
  },
  {
    id: "urhw3837ehalod7w02b7835",
    street_no: "225",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "35.77813",
    long: "119.41791"
  }
];

console.log(combine(cafes, places));

I think you can solve this using simply a map and findIndex. Try this:

const result = places.map(item => {
    const index = cafes.findIndex(cafe => cafe.place_id === item.id);

    if (index > -1) {
        item.name = cafes[index].name;
    }
    return item;
});

console.log(result);

I'd probably start by re-mapping the places into an associative array. One way would be like this:

const placeMap = {};
for (let i=0;i< places.length; i++) {
  placeMap[places[i].id] = places[i];
}

Then you can just iterate your cafe list once and update it with location info:

for (let i=0; i< cafes.length; i++) {
  const loc = placeMap[i.place_id];
  loc.name = cafes[i].name;
  loc.place_id = cafes[i].place_id;
  finalArr.push(loc);
}

You can also accomplish this with some of the newer ES6 functions, the advantage here is that you iterate each array only 2x, where the newer functions might require more iterations (not a big deal normally, but good to keep in mind w/ larger data sets).

  const cafes = [
  {
    name: "Bazaar Cafe",
    place_id: "kjk234g4gcvfx8usg1l33pi",
  },
  {
    name: "Ashley's Cafe",
    place_id: "12hydbdf76sljfts87sbfis",
  },
  {
    name: "Avenue Cafe",
    place_id: "skjd86svvfdrsv55svbvf3f",
  },
  {
    name: "Hi-Lo Cafe",
    place_id: "mjdhgetr4pojfyts22fzfsh",
  },
  {
    name: "California Chicken Cafe",
    place_id: "12hydbdf76sljfts87sbfis",
  },
  {
    name: "Avenue Bakery Cafe",
    place_id: "jahgde7wgdiau8ewsahgosd",
  },
  {
    name: "Philz Coffee",
    place_id: "urhw3837ehalod7w02b7835",
  },
];
const places = [
  {
    id: "jahgde7wgdiau8ewsahgosd",
    street_no: "60H",
    locality: "Solomos Island Road",
    postal_code: "20688",
    lat: "36.7783 N",
    long: "119.4179 W",
  },
  {
    id: "12hydbdf76sljfts87sbfis",
    street_no: "1B",
    locality: "Macarthur Blvd",
    postal_code: "20619",
    lat: "38.1781 N",
    long: "118.4171 W",
  },
  {
    id: "kjk234g4gcvfx8usg1l33pi",
    street_no: "45250",
    locality: "Worth Avenue, Unit A",
    postal_code: "20619",
    lat: "36.1152",
    long: "117.521",
  },
  {
    id: "saswe3s6yydtdr52hsd72yst",
    street_no: "1X",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "36.7783",
    long: "119.4179",
  },
  {
    id: "skjd86svvfdrsv55svbvf3f",
    street_no: "7S",
    locality: "Three Notch Road",
    postal_code: "20619",
    lat: "36.83",
    long: "119.6",
  },
  {
    id: "mjdhgetr4pojfyts22fzfsh",
    street_no: "22803",
    locality: "Gunston Dr Lexington Park",
    postal_code: "20688",
    lat: "35.7788",
    long: "119.979",
  },
  {
    id: "urhw3837ehalod7w02b7835",
    street_no: "225",
    locality: "Macarthur Blvd",
    postal_code: "20687",
    lat: "35.77813",
    long: "119.41791",
  },
];

function combineById (cafes, places) {
  const finalArr = [];
  const set = new Set();

  for (const cafe of cafes) { 
    let cafeName = cafe.name;
    for (const place of places) {
      if (cafe.place_id === place.id ) {
      finalArr.push({...cafe,...place})       
      }
    } 
  }
  return finalArr;
}
const resultArr = combineById(cafes, places);
console.log(resultArr);
Related