1

I have two objects like:

countries = [
    { id: 1, name: 'India', image: 'thumb15.jpg' },
    { id: 2, name: 'Africa', image: 'thumb11.jpg' },
    { id: 3, name: 'Kenya', image: 'thumb10.jpg' }
];

cities = [
    { id: 1, name: 'Ahmedabad', country_id: 1 },
    { id: 2, name: 'Vadodara', country_id: 1 },
    { id: 3, name: 'Cairo', country_id: 2 },
    { id: 4, name: 'Kinshasa', country_id: 2 },
    { id: 5, name: 'Luanda', country_id: 2 },
    { id: 6, name: 'Nairobi', country_id: 3 },
    { id: 7, name: 'Nakuru', country_id: 3 },
    { id: 8, name: 'Mombasa', country_id: 3 },
];

I want to combine these two Objects, just like SQL have INNER JOIN

for example, I want to perform below operation (query) on the above two objects,

SELECT * from countries INNER JOIN cities ON cities.country_id = countries.id

and my expected output will look like:

expected_result = [
    { id: 1, name: "Ahmedabad", country_id: 1, country_name: "India", country_image: "thumb15.jpg" },
    { id: 2, name: "Vadodara", country_id: 1, country_name: "India", country_image: "thumb15.jpg" },
    { id: 3, name: "Cairo", country_id: 2, country_name: "Africa", country_image: "thumb11.jpg" },
    { id: 4, name: "Kinshasa", country_id: 2, country_name: "Africa", country_image: "thumb11.jpg" },
    { id: 5, name: "Luanda", country_id: 2, country_name: "Africa", country_image: "thumb11.jpg" },
    { id: 6, name: "Nairobi", country_id: 3, country_name: "Kenya", country_image: "thumb10.jpg" },
    { id: 7, name: "Nakuru", country_id: 3, country_name: "Kenya", country_image: "thumb10.jpg" },
    { id: 8, name: "Mombasa", country_id: 3, country_name: "Kenya", country_image: "thumb10.jpg" }
];

Thanks in advance.

coderman401
  • 582
  • 3
  • 17
  • Please learn [the difference between JSON and the Array or Object Literal Notation](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation). – str Mar 02 '20 at 09:56
  • Thanks @str. I'll read this. – coderman401 Mar 02 '20 at 09:57

3 Answers3

1

You could take a hash table for all items of countries, where id is the key and the value is a new object in the wanted format.

{
    1: {
        country_name: "India",
        image: "thumb15.jpg"
    },
    2: {
        country_name: "Africa",
        image: "thumb11.jpg"
    },
    3: {
        country_name: "Kenya",
        image: "thumb10.jpg"
    }
}

Then map a new objects with the original key/value and new properties from the hash table.

Methods used, in order of appearance:

var countries = [{ id: 1, name: 'India', image: 'thumb15.jpg' }, { id: 2, name: 'Africa', image: 'thumb11.jpg' }, { id: 3, name: 'Kenya', image: 'thumb10.jpg' }],
    cities = [{ id: 1, name: 'Ahmedabad', country_id: 1 }, { id: 2, name: 'Vadodara', country_id: 1 }, { id: 3, name: 'Cairo', country_id: 2 }, { id: 4, name: 'Kinshasa', country_id: 2 }, { id: 5, name: 'Luanda', country_id: 2 }, { id: 6, name: 'Nairobi', country_id: 3 }, { id: 7, name: 'Nakuru', country_id: 3 }, { id: 8, name: 'Mombasa', country_id: 3 }],
    countriesH = countries.reduce((r, { id, name: country_name, ...o }) =>
        (r[id] = { country_name, ...o }, r), {}),
    result = cities.map(o => ({ ...o, ...countriesH[o.country_id] }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Hi, Thanks. This solution worked for me, but I didn't understand what you have done. Can you please explain it to me. – coderman401 Mar 02 '20 at 10:15
1

It is possible to use map function and Map collection to get desired country:

const uniqueCountries = new Map(countries.map(s => [s.id, s]));
const result = cities.map(s => ({ ...s, 
    country_name: uniqueCountries.get(s.country_id).name }));

An example:

let countries = [
    { id: 1, name: 'India', image: 'thumb15.jpg' },
    { id: 2, name: 'Africa', image: 'thumb11.jpg' },
    { id: 3, name: 'Kenya', image: 'thumb10.jpg' }
];

let cities = [
    { id: 1, name: 'Ahmedabad', country_id: 1 },
    { id: 2, name: 'Vadodara', country_id: 1 },
    { id: 3, name: 'Cairo', country_id: 2 },
    { id: 4, name: 'Kinshasa', country_id: 2 },
    { id: 5, name: 'Luanda', country_id: 2 },
    { id: 6, name: 'Nairobi', country_id: 3 },
    { id: 7, name: 'Nakuru', country_id: 3 },
    { id: 8, name: 'Mombasa', country_id: 3 },
];

 const uniqueCountries = new Map(countries.map(s => [s.id, s]));
 const result = cities.map(s => ({ ...s, 
     country_name: uniqueCountries.get(s.country_id).name }));
 console.log(result);

UPDATE:

map method creates new array from the calling array. In addition, you can add new properties to your object you want:

let countries = [
    { id: 1, name: 'India', image: 'thumb15.jpg' },
    { id: 2, name: 'Africa', image: 'thumb11.jpg' },
    { id: 3, name: 'Kenya', image: 'thumb10.jpg' }
];

const countriesWithShortCountryNames = countries.map(s=> ({...s, 
   shortName: s.name.substring(0, 3)}))
console.log(countriesWithShortCountryNames)

Map collection:

The Map object holds key-value pairs and remembers the original insertion order of the keys.

StepUp
  • 36,391
  • 15
  • 88
  • 148
  • Hi, Thanks. This solution also worked for me, but I didn't aware of javascript `map` and `Map` collection. So I didn't understand. Can you please provide some information to learn this concept. – coderman401 Mar 02 '20 at 10:16
0

I wrote a library (which emulates dotnet's linq) which makes this a breeze:

import { blinq } from "blinq";
//...    
const joinedData = blinq(countries)
  .join(
    cities,
    co => co.id,
    ci => ci.country_id,
    (country, city) => ({ country, city })
  )
  .toArray();

const {
  blinq
} = window.blinq;

const countries = [{
    id: 1,
    name: "India",
    image: "thumb15.jpg"
  },
  {
    id: 2,
    name: "Africa",
    image: "thumb11.jpg"
  },
  {
    id: 3,
    name: "Kenya",
    image: "thumb10.jpg"
  }
];

const cities = [{
    id: 1,
    name: "Ahmedabad",
    country_id: 1
  },
  {
    id: 2,
    name: "Vadodara",
    country_id: 1
  },
  {
    id: 3,
    name: "Cairo",
    country_id: 2
  },
  {
    id: 4,
    name: "Kinshasa",
    country_id: 2
  },
  {
    id: 5,
    name: "Luanda",
    country_id: 2
  },
  {
    id: 6,
    name: "Nairobi",
    country_id: 3
  },
  {
    id: 7,
    name: "Nakuru",
    country_id: 3
  },
  {
    id: 8,
    name: "Mombasa",
    country_id: 3
  }
];

const joinedData = blinq(countries)
  .join(
    cities,
    co => co.id,
    ci => ci.country_id,
    (country, city) => ({
      country,
      city
    })
  )
  .toArray();

console.log(JSON.stringify(joinedData, null, 2))
<script src="https://cdn.jsdelivr.net/npm/blinq"></script>
spender
  • 117,338
  • 33
  • 229
  • 351