Combining items with nested Map structures

I am in need of merging multiple JavaScript objects recursively. These objects contain number properties that need to be added together during the merge process. Additionally, they also have Map properties. Below is an example of how my object appears in the Developer Console:

byGender:Map
    0:{"Male" => 9}
        key:"Male"
        value:9
    1:{"Female" => 11}
        key:"Female"
        value:11
byType:Map
    0:{"Teens" => Object}
        key:"Teens"
        value:Object
            byGender:Map
                0:{"Guys" => 7}
                    key:"Guys"
                    value:7
                1:{"Girls" => 10}
                    key:"Girls"
                    value:10
            total:17
    1:{"Chaperones" => Object}
        key:"Chaperones"
        value:Object
            byGender:Map
                0:{"Ladies" => 1}
                    key:"Ladies"
                    value:1
                1:{"Men" => 2}
                    key:"Men"
                    value:2
            total:3
total:42

My goal is to merge these Map objects and add the numbers of matching keys together.

I'm currently using _.mergeWith along with a customizer function. While I am able to merge simple number properties successfully, I am facing difficulty in merging the Map objects as well. Currently, my customizer merger function replaces the Map object, causing the last one to overwrite the previous. Here's the customizer function I am using with _.mergeWith:

var merger = function (a, b) {
    if (_.isNumber(a)) {
      return a + b;
    } else {
      return _.mergeWith(a, b, merger);
    }
};

Searching for solutions has been challenging because the keyword "map" mainly returns results related to .map(), rather than focusing on the Map object itself.

Answer №1

After much trial and error, I finally developed a merger function that gets the job done. While it may not be as sleek as I initially envisioned, I decided to share it here just in case anyone else is grappling with a similar issue.

Admittedly, the drawback of my solution is its lack of versatility. It seems to be tailored to a specific set of structures and recursion complexities, which could pose challenges when adapting it for different scenarios.

function merger(source, mergeTarget) {
    if (_.isNumber(source)) {
      return source + mergeTarget;
    } 
    else if (_.isMap(source)) {
        var newMap = new Map();
        source.forEach(function(value,key,root){
            var newValue = mergeTarget.get(key);
            if(_.isNumber(value))
                newMap.set(key,value + newValue);
            else if (_.isObject(value)){
                var newObj = {};
                _.mergeWith(newObj,value,newValue,merger);
                newMap.set(key,newObj);
            }
        });
        return newMap;
    }
 }

Answer №2

While it may seem like this information is coming in a bit late, there's still value in sharing it for others who might benefit:

If you're looking to merge Maps, there's a simple method that can be used:

const mergedMap = new Map([...map1, ...map2]);

If you need to handle conflicting values during the merge process, consider using the mapCollectInto function from the big-m library created specifically for this purpose (source code):

const { mapCollectInto, reconcileAdd } = "big-m";

const mergedMap = mapCollectInto(
  map1,
  map2,
  reconcileAdd()
);

Another option, without modifying map2:

const { mapCollect, mapConcat, reconcileAdd } = "big-m";

const mergedMap = mapCollect(
  mapConcat(map1, map2),
  reconcileAdd()
);

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

AngularJS creates a new window in your application

I have created two html pages named web.html and addroute.html. Both pages are built with bootstrap. The angularjs script includes two controllers: webctrl and addctrl. In web.html, there is a button that, when clicked, opens the addroute.html page. I am ...

Exploring the potential of Bootstrap/bootflat and jQuery progress bars

I am attempting to display and animate a progress bar while loading an HTML page into a div using jQuery. The progress bar I am using is from Bootstrap (Bootflat) and has the following structure: <div class="progress" style="visibility:hidden;"> ...

Discover the concealed_elem annotations through the power of JavaScript

As I work on my new website, I am struggling with narrowing down the web code. I came across a solution that seems fitting for what I need, but unfortunately, I can't seem to make it work: I attempted the non-jQuery solution, however, I must be missi ...

When attempting to click on another button, the action does not seem to be working as expected. The button in question has a

Greetings! I have encountered an issue where both of my buttons work perfectly fine individually, but when I attempt to use Button A to click Button B using JavaScript, it doesn't seem to work. I can confirm that Button A functions correctly as the al ...

When using the `array.join` method with nested arrays, it does not automatically include spaces in the output

function convertArrayToString(arr) { // Your solution goes here. let str = arr.join(", "); return str; } const nestedValues = [5, 6, [7], ["8", ["9", ["10" ]]]]; const convertedString = convertArrayToString(nestedValues); console.log(convertedString ...

Is the Expand All / Collapse All feature malfunctioning when used with a tree table?

I have been working on implementing the Expand All/Collapse All feature for a nested tree table, but unfortunately, I am not achieving the desired output. I referred to a related question on this topic which can be found here. You can also view the code on ...

Leveraging Redux and React to efficiently map state to props, while efficiently managing large volumes of data and efficiently

Utilizing sockets for server listening, the Redux store undergoes continuous updates with a vast amount of data. While updating the store is quick, the process of connecting the state to the component through the redux connect function seems to be slower, ...

A guide on organizing an array of objects by a specific property using a separate array

Here is the array I am working with: var arr = [ { count: 27, dataRil: "08/06/21", subCateg: "FISH", }, { count: 22, dataRil: "08/06/21", subCateg: "DOG", }, { count: 28, dat ...

What is the best way to retrieve the output of MongoDB's collection.aggregate() within a NodeJS callback function?

In my database, I have a users collection with the following data: { "_id" : ObjectId("5b29ba37cd0b1726068731c3"), "name" : "Gym Dog", "profilePicUrl" : "https://i.imgur.com/mPStaKV.png", "totalProgress" : { "goal" : 300, "progress ...

Utilizing React and Material-UI to create an autocomplete feature for words within sentences that are not the first word

Looking to enable hashtag autocomplete on my webapp, where typing #h would display a menu with options like #hello, #hope, etc. Since I'm using material-ui extensively within the app, it would be convenient to utilize the autocomplete component for th ...

Displaying Grunt Command-Line Output in Browser

Is there a straightforward method to display the command-line output of a grunt task in a browser? Essentially, I want to showcase the input and/or output of a command line process within a browser window. While I am aware that I could develop a custom app ...

Attempting to populate mongoDB with an array of strings, unsure of how to define the model for this

Currently, I am in the process of testing some seed data using mongoDB for an ecommerce store. I am encountering an error while trying to parse an array of categories into the products model. const { Schema, model } = require('mongoose'); const d ...

Passing data to server-side PHP script using AJAX technology

Currently, I'm facing an issue with passing variables to a PHP script using onclick. It seems that I am making a mistake somewhere. To demonstrate the problem, let's say I have the following code snippet in my main page: <img src="myImage.jp ...

How do RxJS collection keys compare?

Is there a more efficient way to compare two arrays in RxJS? Let's say we have two separate arrays of objects. For example: A1: [{ name: 'Sue', age: 25 }, { name: 'Joe', age: 30 }, { name: 'Frank', age: 25 }, { name: & ...

Starting from TypeScript version 5.6, `Buffer` cannot be categorized as either `ArrayBufferView` or `Uint8Array | DataView`

Struggling to make the transition to TypeScript 5.6 Beta, I am encountering these error messages within the node_modules directory. Without making any other modifications, how can I resolve these errors? node_modules/@types/node/buffer.d.ts:632:19 - error ...

Is it possible to create clickable titles in highcharts that also interact with bootstrap popovers?

Hello, I'm trying to figure out how to turn the title in highcharts into a clickable link that works with bootstrap's popover feature. You can find an example of what I'm working on here: http://jsfiddle.net/287JP/4/ $(function () { ...

What is the most effective way to remove harmful HTML (such as XXS) from content submissions?

My content submission form has various input fields that are directly entered into the database upon submission and then printed when requested. After recognizing this as a security concern, I am looking for a way to remove malicious HTML (XSS) while stil ...

Managing a variable amount of form input values

One of the challenges I'm facing is handling a form that includes a link to open a modal window for entering additional information. Since this additional information is generated dynamically, I need to find a way to create these items as they are add ...

vue-router default route for children

Currently, I am working on a Vue 2.x application and utilizing vue-router for routing purposes. In certain situations, I need to directly display a child vue. The template structure is as follows: | voice 1 | voice 2 | voice 3 | | submenu 1 | submen ...

Explanation of the JCrop showPreview function

I'm struggling to grasp the exact purpose and functionality of this specific function. This function is part of JCrop, a popular jQuery cropping plugin, and it calculates how to display a preview image next to an image intended for cropping. Essential ...