0

I have two arrays of objects that I need to merge together to only get one array of object. There is a lot of objects, both have more than 500+ objects

This is an exemple of the structure of the two array of objects :

let API = [
  {
    actif: true,
    id: 8,
    creation_user: "David",
    date_creation: "févr  4 2022 12:17PM",
    description: "A description",
    version: "v1r1"
  },
  {
    actif: true,
    id: 10,
    creation_user: "Julien",
    date_creation: "févr  10 2022 12:17PM",
    description: "A description",
    version: "v1r2"
  },
  {
    actif: false,
    id: 20,
    creation_user: "Tom",
    date_creation: "févr  10 2022 12:17PM",
    description: "A description",
    version: "v1r2"
  }
]

let Parameters = [
  {
    id: 10,
    name: "codeRR",
    type: "string"
  },
  {
    id: 20,
    name: "codeAA",
    type: "string"
  },
  {
    id: 20,
    name: "codeCC",
    type: "string"
  }
]

As we can see, they both have an ID, this ID is the same in both arrays. But not everytime, API can have no parameter.

What i'm trying to achieve is to get in the second array, the "name" and "type", and to add it to the first array (or in a new array).

I've tried with .map on the first array (also tried with the second one) :

let Ressource = api.map(item => Object.assign({}, item, parametre.find(target => target.id === item.id)));
 
 // Result of Ressource
 
 [
  {
    actif: true,
    id: 8,
    creation_user: "David",
    date_creation: "févr  4 2022 12:17PM",
    description: "A description",
    version: "v1r1";
    name: "codeRR",
    type: "string
  }
 ]
 
 // Want I want :
 [
  {
    actif: true,
    id: 8,
    creation_user: "David",
    date_creation: "févr  4 2022 12:17PM",
    description: "A description",
    version: "v1r1",
    parameter: [
      {
        name: "codeRR",
        type: "string
      },
      {
        name: "codePP",
        type: "string
      }
    ]
  }
 ]

But when an API have multiple parameter it overwrite the previous one. Is it possible to make something like this in my API

parameter: [{"name": "codeRR", type: "string"}, {"name": "codePP", "type": "string"}]
4
  • A) id = 8 is present in API but not present in Parameters array. So, how do we get the resulting Resource to have name: codeRR for id = 8? B) Would you please update the question with what is expected result for id = 20?.
    – jsN00b
    Commented May 31, 2022 at 7:36
  • Does this answer your question? JavaScript merging objects by id
    – pilchard
    Commented May 31, 2022 at 7:38
  • yes, id = 8 is not present in Parameters because sometime API doesn't have a parameter, I will edit my question.
    – Quentin
    Commented May 31, 2022 at 7:39
  • also Merge two array of objects based on a key
    – pilchard
    Commented May 31, 2022 at 7:39

3 Answers 3

1
  1. Group the Parameters array by their id using Array.prototype.reduce, this would give an object where the keys are the ids and the values are an array of parameter objects.

  2. Loop over the API array and using the object created above add the parameter property wherever the parameter information is available.

let 
  API = [
    { actif: true, id: 8, creation_user: "David", date_creation: "févr  4 2022 12:17PM", description: "A description", version: "v1r1" },
    { actif: true, id: 10, creation_user: "Julien", date_creation: "févr  10 2022 12:17PM", description: "A description", version: "v1r2" },
    { actif: false, id: 20, creation_user: "Tom", date_creation: "févr  10 2022 12:17PM", description: "A description", version: "v1r2" },
  ],
  Parameters = [
    { id: 10, name: "codeRR", type: "string" },
    { id: 20, name: "codeAA", type: "string" },
    { id: 20, name: "codeCC", type: "string" },
  ],
  ParametersGroup = Parameters.reduce((r, p) => ((r[p.id] ??= []).push(p), r), {}),
  APIWithParams = API.map((o) => ({
    ...o,
    ...(ParametersGroup[o.id] && { parameters: ParametersGroup[o.id] }),
  }));

console.log(APIWithParams);

If you want to handle single parameter and multiple parameters differently, then refer to the solution below:

let 
  API = [
    { actif: true, id: 8, creation_user: "David", date_creation: "févr  4 2022 12:17PM", description: "A description", version: "v1r1" },
    { actif: true, id: 10, creation_user: "Julien", date_creation: "févr  10 2022 12:17PM", description: "A description", version: "v1r2" },
    { actif: false, id: 20, creation_user: "Tom", date_creation: "févr  10 2022 12:17PM", description: "A description", version: "v1r2" },
  ],
  Parameters = [
    { id: 10, name: "codeRR", type: "string" },
    { id: 20, name: "codeAA", type: "string" },
    { id: 20, name: "codeCC", type: "string" },
  ],
  ParametersGroup = Parameters.reduce((r, p) => ((r[p.id] ??= []).push(p), r), {}),
  APIWithParams = API.map((o) => {
    const paramsForId = ParametersGroup[o.id];
    return {
      ...o,
      ...(paramsForId && (paramsForId.length > 1 ? { parameters: paramsForId } : paramsForId[0])),
    };
  });

console.log(APIWithParams);

Note: Finding the parameter for an id again and again is not optimal. Hence we've created an object beforehand and referenced it while adding the parameter information.

Other relevant documentations:

7
  • Thanks you for the documentation, I truly need it, always having a bad time performing such merge and arrays of objects in general.
    – Quentin
    Commented May 31, 2022 at 8:15
  • 1
    @Quentin I've also added a note in my answer, I'd recommend going through that. Since you mentioned that the arrays could be large, it's not optimal to find or filter (or anything that takes linear time) again and again. Commented May 31, 2022 at 8:22
  • 1
    I see, again, thanks you, I was a bit concerned about performance since it's was taking some time to build the array with a find or filter. Will read and take note from your links !
    – Quentin
    Commented May 31, 2022 at 8:40
  • By the way, is there any optimal way to display all of the array ?
    – Quentin
    Commented May 31, 2022 at 9:00
  • You want to render thousands of items at once? Usually that's not required and only a portion of the data is rendered at once. But in case you want to render everything at once, you can. Commented May 31, 2022 at 11:29
1

If the parameters have the same attributes they will be overwritten.

if you need both of them you need to store them in an array

like this

const decorate = (data, parameters) => data.map(d => ({...d, parameters: parameters.filter(({id}) => d.id === id)}))




let API = [
  {
    actif: true,
    id: 8,
    creation_user: "David",
    date_creation: "févr  4 2022 12:17PM",
    description: "A description",
    version: "v1r1"
  },
  {
    actif: true,
    id: 10,
    creation_user: "Julien",
    date_creation: "févr  10 2022 12:17PM",
    description: "A description",
    version: "v1r2"
  },
  {
    actif: false,
    id: 20,
    creation_user: "Tom",
    date_creation: "févr  10 2022 12:17PM",
    description: "A description",
    version: "v1r2"
  }
]

let Parameters = [
  {
    id: 10,
    name: "codeRR",
    type: "string"
  },
  {
    id: 20,
    name: "codeAA",
    type: "string"
  },
  {
    id: 20,
    name: "codeCC",
    type: "string"
  }
]

console.log(decorate(API,Parameters ))

1
  • Solved my problems with your code, so filter was far better than just a find. And yes, i need both, making sure I don't miss something
    – Quentin
    Commented May 31, 2022 at 8:17
1

You're almost there. You can add extra logic for your map to handle multiple and single parameters separately.

let API = [{
    actif: true,
    id: 8,
    creation_user: "David",
    date_creation: "févr  4 2022 12:17PM",
    description: "A description",
    version: "v1r1"
  },
  {
    actif: true,
    id: 10,
    creation_user: "Julien",
    date_creation: "févr  10 2022 12:17PM",
    description: "A description",
    version: "v1r2"
  },
  {
    actif: false,
    id: 20,
    creation_user: "Tom",
    date_creation: "févr  10 2022 12:17PM",
    description: "A description",
    version: "v1r2"
  }
]

let Parameters = [{
    id: 10,
    name: "codeRR",
    type: "string"
  },
  {
    id: 20,
    name: "codeAA",
    type: "string"
  },
  {
    id: 20,
    name: "codeCC",
    type: "string"
  }
]

const result = API.map((data) => {
  const updatedData = Object.assign({}, data)
  const foundParameters = Parameters.filter(({
    id
  }) => id === data.id)
  if (foundParameters.length === 0) {
    return data
  }

  if (foundParameters.length === 1) {
    return Object.assign(updatedData, foundParameters[0])
  } else {
    return Object.assign(updatedData, {
      parameter: foundParameters.map(({
        name,
        type
      }) => ({
        name,
        type
      }))
    })
  }
});

console.log(result)

1
  • I never thought about this extra logic, I take note !
    – Quentin
    Commented May 31, 2022 at 8:14

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.