drago
drago

Reputation: 1283

Merging 3 arrays WHERE ids match in javascript?

Lets say I have 3 arrays that look like this:

var siteS1 = [{
    Date: '2021-02-02 11:19',
    siteid: 77,
},
{
    Date: '2021-02-02 11:19',
    siteid: 76,
},
{
    Date: '2021-02-02 11:19',
    siteid: 66,
},
{
    Date: '2021-02-02 11:19',
    siteid: 96,
}];


var siteS2 = [{
    Date: '2021-02-02 11:19',
    siteid: 77,
},
{
    Date: '2021-02-02 11:19',
    siteid: 76,
},
{
    Date: '2021-02-02 11:19',
    siteid: 66,
},
{
    Date: '2021-02-02 11:19',
    siteid: 96,
}];

var form = [{
    data: {},
    siteid: 77,
},
{
    data: {},
    siteid: 76,
},
{
    data: {},
    siteid: 66,
},
{
    data: {},
    siteid: 96,
}];

I need to to merge these 3 arrays where the siteid matches.

The end result should look like this:

[{
    "siteS1": { "Date": "2021-10-31 20:22" },
    "form": [{}],
    "siteS2": { "Date": "2021-10-31 20:22" }
}, {
    "siteS1": { "Date": "2021-10-31 20:22" },
    "form": [{}],
    "siteS2": { "Date": "2021-10-31 20:22" }
}]

Tried a couple of ways but I can't get the result I need.

I tried this:

const mergedArr = siteS1.map((item, i) => {
  if (item.siteid === siteS2[i].siteid) {
    return Object.assign({}, item, siteS2[i]);
  }
});

and this:

Array.prototype.push.apply(siteS1,siteS2); 

EDIT:

The form array or the siteS2 could be empty (blank arrays).

Upvotes: 0

Views: 78

Answers (4)

Ben Stephens
Ben Stephens

Reputation: 3371

I would collect the data into a map first and then create an array from that.

const siteS1 = [{"Date":"2021-02-02 11:19","siteid":77},{"Date":"2021-02-02 11:19","siteid":76},{"Date":"2021-02-02 11:19","siteid":66},{"Date":"2021-02-02 11:19","siteid":96}];
const siteS2 = [{"Date":"2021-02-02 11:19","siteid":77},{"Date":"2021-02-02 11:19","siteid":76},{"Date":"2021-02-02 11:19","siteid":66},{"Date":"2021-02-02 11:19","siteid":96}];
const form = [{"data":{},"siteid":77},{"data":{},"siteid":76},{"data":{},"siteid":66},{"data":{},"siteid":96}];

const add_site_to_map = (map, site, key_name) => {
  site.forEach(({ siteid, ...other }) => {
    map.set(
      siteid,
      Object.assign(map.get(siteid) ?? {}, { [key_name]: other })
    );
  });
};

const add_form_to_map = (map, form, key_name) => {
  form.forEach(({ siteid, data, ...other }) => {
    const current = map.get(siteid) ?? {};
    
    map.set(
      siteid,
      Object.assign(current, { [key_name]: (current[key_name] ?? []).concat(data) })
    );
  });
};

const get_merged_array = (sites, forms) => {
  const map = new Map();
  
  Object.entries(sites).forEach(([key, site_values]) => {
    add_site_to_map(map, site_values, key)
  });
  
  Object.entries(forms).forEach(([key, form_values]) => {
    add_form_to_map(map, form_values, key)
  });
  
  return [...map.values()];
};



console.log(get_merged_array({ siteS1, siteS2 }, { form }));

Upvotes: 2

aerial
aerial

Reputation: 1198

Here is one way to do it:

var siteS1 = [
  { Date: '2021-02-02 11:19', siteid: 77},
  { Date: '2021-02-02 11:19', siteid: 76 },
  { Date: '2021-02-02 11:19', siteid: 66 },
  { Date: '2021-02-02 11:19', siteid: 96 },
]

var siteS2 = [
  { Date: '2021-02-02 11:19', siteid: 77 },
  { Date: '2021-02-02 11:19', siteid: 76 },
  { Date: '2021-02-02 11:19', siteid: 66 },
  { Date: '2021-02-02 11:19', siteid: 96 },
]

var form = [
  { data: {}, siteid: 77 },
  { data: {}, siteid: 76 },
  { data: {}, siteid: 66 },
  { data: {}, siteid: 96 },
]



const result = siteS1.map(obj => {
  const currentID = obj.siteid
  return {
    siteS1: obj.Date,
    siteS2: siteS2.find(obj => obj.siteid == currentID)?.Date || [],
    form: form.find(obj => obj.siteid == currentID)?.data || [],
  }
})

console.log(result)

Upvotes: 1

Bad Dobby
Bad Dobby

Reputation: 871

1. get list of merged and uniqued siteid from list of arrays

const merge = (arrayList) => {
  // extract each `siteid` from all arrays
  const siteids = arrayList
    .map(array => array.map(item => item.siteid))
    .flat()

  // make each siteid to be unique in the array of siteid
  return Array.from(new Set(siteids))
}

2. populate the array of siteid with the data from three original arrays

// find item from an array by `siteid` and get properties except `siteid
const find = (siteid, array) => {
  const found = array.find(item => item.siteid === siteid)
  console.log(found)
  if (!found) return undefined // returns undefined if item was not found
  const { siteid: _, ...restFoundData } = found // omit `siteid` from found item
  return restFoundData
}

const populate = (siteids) => siteids.map(siteid => {
  const foundSiteS1 = find(siteid, siteS1) // find data from `siteS1`
  const foundSiteS2 = find(siteid, siteS2) // find data from `siteS2`
  const foundForm = find(siteid, form) // find data from `form`

  return {
    siteS1: foundSiteS1,
    siteS2: foundSiteS2,
    form: foundForm ? [foundForm.data] : [], // empty array if no items matched
  }
})

3. combine all of theese together

populate(merge(siteS1, siteS2, form))

test

var siteS1 = [{
Date: '2021-02-02 11:19',
siteid: 77,
},
{
Date: '2021-02-02 11:19',
siteid: 76,
},
{
Date: '2021-02-02 11:19',
siteid: 66,
},
{
Date: '2021-02-02 11:19',
siteid: 96,
}];


var siteS2 = [{
Date: '2021-02-02 11:19',
siteid: 77,
},
{
Date: '2021-02-02 11:19',
siteid: 76,
},
{
Date: '2021-02-02 11:19',
siteid: 66,
},
{
Date: '2021-02-02 11:19',
siteid: 96,
}];

var form = [{
data: {},
siteid: 77,
},
{
data: {},
siteid: 76,
},
{
data: {},
siteid: 66,
},
{
data: {},
siteid: 96,
}];

const merge = (...arrayList) => {
  const siteids = arrayList
    .map(array => array.map(item => item.siteid))
    .flat()
  return Array.from(new Set(siteids))
}

const find = (siteid, array) => {
  const found = array.find(item => item.siteid === siteid)
  if (!found) return undefined // returns undefined if item was not found
  const { siteid: _, ...restFoundData } = found // omit `siteid` from found item
  return restFoundData
}

const populate = (siteids) => siteids.map(siteid => {
  const foundSiteS1 = find(siteid, siteS1)
  const foundSiteS2 = find(siteid, siteS2)
  const foundForm = find(siteid, form)
  return {
    siteS1: foundSiteS1,
    siteS2: foundSiteS2,
    form: foundForm ? [foundForm.data] : [], // empty array if no items matched
  }
})

const result = populate(merge(siteS1, siteS2, form))
console.log(result)

Upvotes: 2

lovepeacfineapple
lovepeacfineapple

Reputation: 35

const newArray = []
for (let i = 0; i < siteS1.length; i++) {
  for (let j = 0; j < siteS2.length; j++) {
    for (let k = 0; k < form.length; k++) {
      if (siteS1[i].siteid === siteS2[j].siteid && siteS1[i].siteid === form[k].siteid) {
        const item = { "siteS1": { "Date": siteS1[i].Date }, "form": [form[k].data], "site2": { "Date": siteS2[j].Date } }
        newArray.push(item)
      }
    }
  }
}

It is working.

Upvotes: 2

Related Questions