Adding embedded attributes from a different object

I am facing a challenge with two arrays called metaObjects and justObjects.

These arrays consist of objects that share a common property called id.

My goal is to merge properties from the objects in these separate arrays into a new array.

const metaObjects = [
  {
    id: 1,
    metaProp: "metaProp1"
  },
  {
    id: 2,
    metaProp: "metaProp2"
  }
];

const justObjects = [
  {
    id: 1,
    justProp: "justProp1"
  },
  {
    id: 2,
    justProp: "justProp2"
  }
];

This is the desired outcome:

const result= [
    {
      id: 1,
      metaProp: "metaProp1",
      justProp: "justProp1"
    },
    {
      id: 2,
      metaProp: "metaProp2",
      justProp: "justProp2"
    }
  ];

I attempted using nested map functions to achieve this

const combinedObject = justObjects.map(_w => {
  return metaObjects.map(_m => {
    if (_w.id === _m.id) {
      return { ..._m, ..._w };
    }
  });
}, metaObjects);

console.log(combinedObject);

However, I encountered the following error

[ [ { id: 1, metaProp: 'metaProp1', justProp: 'justProp1' },
    undefined ],
  [ undefined,
    { id: 2, metaProp: 'metaProp2', justProp: 'justProp2' } ] ]

I am puzzled about why there are undefined values in the inner arrays.
Additionally, I need to flatten the arrays to align with the expected results provided above.

I have heard about utilizing the composable lens functions from ramda

Could this approach be beneficial in solving my issue?

Answer №1

Similar to customcommander's answer, this approach opts for using groupBy and values instead of sortBy and groupWith. It seems more logical and avoids an unnecessary sort call.

const {pipe, concat, groupBy, prop, values, map, mergeAll} = R

const joinOnId = pipe
  ( concat
  , groupBy (prop ('id'))
  , values
  , map (mergeAll)
  )

const metaObjects = 
  [ { id: 1, metaProp: "metaProp1" }
  , { id: 2, metaProp: "metaProp2" }
  , { id: 3, metaProp: "metaProp3" }  // unique to `meta`
  ]

const justObjects = 
  [ { id: 1, justProp: "justProp1" }
  , { id: 2, justProp: "justProp2" }
  , { id: 4, justProp: "justProp4" }  // unique to `just`
  ]

console.log 
  ( joinOnId (metaObjects, justObjects)
  )
.as-console-wrapper {
  max-height: 100vh !important;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

This function can easily be adapted to accommodate different property names:

const joinOn = (propName) =>
  pipe
    ( concat
    , groupBy (prop (propName))
    , values
    , map (mergeAll)
    )
// ...
const joinOnId = joinOn ('id')

and it can also utilize various key-generation functions:

const joinOn = (keyFn) =>
  pipe
    ( concat
    , groupBy (keyFn)
    , values
    , map (mergeAll)
    )
// ...
const joinOnId = joinOn (prop ('id'))

Answer №2

To combine objects, you can use the find() method to search for the object and then merge them using Object.assign(). Make sure that the object exists in metaObjects before merging.

const metaObjects = [
  {
    id: 1,
    metaProp: "metaProp1"
  },
  {
    id: 2,
    metaProp: "metaProp2"
  }
];

const justObjects = [
  {
    id: 1,
    justProp: "justProp1"
  },
  {
    id: 2,
    justProp: "justProp2"
  }
];

justObjects.forEach(item => {
   let toMerge = metaObjects.find(obj => obj.id === item.id)
   Object.assign(toMerge, item)
})
console.log(metaObjects)

If metaObjects is large, consider storing it as an object with keys based on id for faster lookups without searching each time.

If you prefer not to modify metaObjects, you can use map() on justObjects to create a new array:

const metaObjects = [
  {
    id: 1,
    metaProp: "metaProp1"
  },
  {
    id: 2,
    metaProp: "metaProp2"
  }
];

const justObjects = [
  {
    id: 1,
    justProp: "justProp1"
  },
  {
    id: 2,
    justProp: "justProp2"
  }
];

let newArray = justObjects.map(item => {
   let toMerge = metaObjects.find(obj => obj.id === item.id)
   return Object.assign({}, toMerge, item)
})
// metaObjects remains unchanged
console.log(newArray)

Answer №3

To combine the two arrays, group objects by id (ensuring to sort first), and then merge each grouped item together can be achieved quite simply:

const {
  map,
  mergeAll,
  groupWith,
  eqBy,
  prop,
  concat,
  sortBy,
  pipe
} = R;

const metaObjects = [
  { id: 1,
    metaProp: "metaProp1" },
  { id: 2,
    metaProp: "metaProp2" }];

const justObjects = [
  { id: 1,
    justProp: "justProp1" },
  { id: 2,
    justProp: "justProp2" }];

const process = pipe(
  concat,
  sortBy(prop('id')),
  groupWith(eqBy(prop('id'))),
  map(mergeAll));

console.log(

  process(metaObjects, justObjects)

);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>

Answer №4

To transform an array of objects with an "id" property into an object of objects, I recommend using either the Array.prototype.reduce() method or a simple for loop:

const merged = metaObjects.reduce((acc, cur) => {
    acc[cur.id] = cur;

    return acc;
}, {});

Alternatively:

const merged = {};

for (const obj of metaObjects) {
    merged[obj.id] = obj;
}

Next, iterate through the other array and merge each entry with the object created above:

justObjects.forEach((obj) => {
    merged[obj.id] = Object.assign({}, merged[obj.id], obj);
});

Finally, convert the resulting object back into an array using Object.values:

Object.values(merged);

For example:

const metaObjects = [{
  id: 1,
  metaProp: "metaProp1"
},{
  id: 2,
  metaProp: "metaProp2"
}];

const justObjects = [{
  id: 1,
  justProp: "justProp1"
},{
  id: 2,
  justProp: "justProp2"
},{
  id: 3,
  justProp: "justProp3"
}];

// Create an object from one of the arrays using its id property:

/*
// Alternative using reduce:

const merged = metaObjects.reduce((acc, cur) => {
  acc[cur.id] = cur;
  
  return acc;
}, {});
*/

// Alternative using a for loop:

const merged = {};

for (const obj of metaObjects) {
  merged[obj.id] = obj;
}

// Iterate through the other array and merge it with the existing map:

justObjects.forEach((obj) => {
  merged[obj.id] = Object.assign({}, merged[obj.id], obj);
});

// Convert back to an array of objects:

console.log(Object.values(merged));
.as-console-wrapper {
  max-height: 100vh !important;
}

It is worth noting that this approach will handle cases where either array contains entries with ids not found in the other.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When utilizing AJAX within a for loop, the array position may not return the correct values, even though the closure effectively binds the scope of the current value position

Is this question a duplicate of [AJAX call in for loop won't return values to correct array positions? I am following the solution by Plynx. The issue I'm facing is that the closure fails to iterate through all elements in the loop, although the ...

Send information to modal using Javascript

I am facing an issue when trying to transfer data from JavaScript to a Bootstrap modal. Here is how my code looks: Modal: <div id="myModal" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> ...

Submitting data with ajax in MVC when an option is chosen in a dropdown menu

Within my form, I have multiple dropdown lists. Whenever a user selects an option from one of these dropdowns, I want that value to be saved in the backend database. To avoid reloading the page, I believe using Ajax is the best approach, but I need assista ...

Retrieve data from a list using an API

I am currently working on creating a dynamic list by fetching data from an API. The goal is to display detailed information in a modal when a user clicks on a specific item in the list. While the list itself is functioning properly, I am encountering an i ...

jquery technique for toggling a single button

My goal is to use jQuery to toggle a button rather than the typical paragraph toggling. I want the button to appear and disappear when clicked, while also increasing the "score" upon each click and decreasing it when the button reappears. Can anyone guide ...

Retrieve the player's name from the database using jQuery

How can I retrieve the text value from my scores table in the database? Here is an image of my score table: https://i.stack.imgur.com/CUiMw.png The Player_name is stored as Player_id, which is a foreign key from the players' table. While I c ...

Accessing and displaying all states in $stateProvider using AngularJS and ui-router

Here's a simple question: how can I find all instances of $stateProvider.state in my app.js, which is my AngularJS config file? In the past with ngRoute, I could achieve this by using a similar approach in my .run() block: .run(function ($route) { ...

Tips for effectively managing 404 errors in Angular 10 with modular routing

I'm facing challenges with handling 404 pages within an Angular 10 application that utilizes modular routing architecture. Here is the structure of my code: |> app |-- app.module.ts |-- app-routing.module.ts |-- app.component{ts, spec.ts, scss, ht ...

Using Vuex: Delay dispatch of action until websocket response received

Let's look at the given scenario and premises: To populate a chat queue in real time, it is necessary to establish a connection to a websocket, send a message, and then store the data in a websocket store. This store will handle all the websocket sta ...

I am facing an issue where my Javascript hide and show function is not working properly when clicked. Despite not giving

I am currently working on a Javascript onClick function to toggle the visibility of content in a lengthy table. I initially set part of the table's class to display: "none" and added a button to show the hidden content when clicked. However, nothing i ...

angularjs determining the appropriate time to utilize a directive

I have been delving into JavaScript and AngularJS for approximately a month now, but I still find myself unsure of when to use directives. For example: I am looking to display appointments in a table with the date as the table header. I envision having bu ...

Exploring the syntax of ReactJS state management with setState

Trying to wrap my head around the following syntax in my React app. I am looking to understand how the code inside setState() works. this.getSomePromise().then( // resolve callback function someImg => this.setState(prevState => ( ...

Determine the worth of various object attributes and delete them from the list

Currently, my dataset is structured like this: { roof: 'black', door: 'white', windows: 8 }, { roof: 'red', door: 'green', windows: 2 }, { roof: 'black', door: 'green', windows: ...

The presence of 'touched' within Angular validation is causing a delay in method execution

Upon utilizing this validation method, it became apparent: <label>Password</label> <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': f.password.touc ...

scope.$digest completes before triggering scope.$watch in Karma unit tests

I am interested in testing this specific directive: .directive('uniqueDirective', function () { return { restrict: 'A', scope: { uniqueDirective: '@', tooltip: '@', placement: '@&apo ...

Loop through the AJAX response containing JSON data

Need assistance in extracting specific information from each hotel key and its rates within this JSON structure using JavaScript: [ { "auditData": { "processTime": "1545", "timestamp": "2016-04-08 04:33:17.145", ...

What could be causing the absence of any displayed content in FirBug when typing in the Google Search box?

Many websites with a suggestion box feature utilize AJAX requests to communicate with the server and receive responses. I attempted to intercept the requests made by the Google search box, but the FireBug console did not display anything. However, when us ...

"Error alert: The specified property 'Iscontains' cannot be read because it is undefined" appears in the script for this video

I am currently utilizing AJAX to interact with my backend code. I retrieve URLs from the database and then render them onto the DOM, displaying videos accordingly. However, I am encountering an issue where Uncaught TypeError: Cannot read property ' ...

How to troubleshoot NodeJS errors when piping data from tar packing to webhdfs

I am currently in the process of developing a node application that utilizes Hadoop as a long-term storage solution for data when one of my services is not operational. To optimize efficiency and minimize processing time due to anticipated high transfer vo ...

Tips for utilizing javascript document.createElement, document.body, and $(document) in an HTML web resource for Microsoft CRM code reviews

Let me start off by saying that I am not a regular blogger and I am feeling quite confused. If my question is unclear, please provide guidance for improvement. I recently submitted a Microsoft CRM PlugIn to the Microsoft Code Review. I am new to Javascrip ...