合并包含嵌套Map对象的对象

时间:2016-03-25 14:59:05

标签: javascript merge lodash

我想要以递归方式合并多个javascript对象。 这些对象有一些数字属性,我在合并时将它们加在一起。 对象还具有一些Map属性。以下是我的对象在Developer Console中的外观示例:



 $('#opiniondt tbody td.details-control').on('click', function () {
     var tr = $(this).closest('tr');
     var row = table.row( tr );   

     if ( row.child.isShown() ) {
         //  This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
     }
     else {
        // Open this row
        row.child( format(iTableCounter) ).show();
        tr.addClass('shown');
        // try datatable stuff
        oInnerTable = $('#opiniondt_' + iTableCounter).dataTable({
            data: sections, 
            autoWidth: true, 
            deferRender: true, 
            info: false, 
            lengthChange: false, 
            ordering: false, 
            paging: false, 
            scrollX: false, 
            scrollY: false, 
            searching: false, 
            columns:[ 
               { data:'refCount' },
               { data:'section.codeRange.sNumber.sectionNumber' }, 
               { data:'section.title' }
             ]
        });
        iTableCounter = iTableCounter + 1;
    }
 });




我想合并这些Map对象的值,以便将所有匹配键的数量相加。

我使用_.mergeWith及其自定义程序功能。我可以成功合并简单的数字属性,但是如何合并Map对象呢?现在我的定制器合并功能只是替换了Map对象,所以最后一个获胜。 这是我使用_.mergeWith

的定制器功能



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




搜索时很难找到答案因为" map"关键字只是拉起一堆.map()结果,而不是Map对象。

2 个答案:

答案 0 :(得分:0)

我提出了一个合并功能。不像我希望的那样优雅,但发布在这里以防其他任何人坚持这个。

唯一的缺点是它不是我想要的一般解决方案。我认为这需要改变以适应不同类型的结构和递归复杂性。

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;
    }
 }

答案 1 :(得分:0)

这显然为时已晚,无法提供帮助,但也许会对其他人有所帮助?

由于地图是可迭代的,因此有一种很简单的方法可以将它们实际合并:

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

要通过合并冲突值来处理冲突值,一种选择是使用我为此目的而编写的mapCollectInto库中的big-m函数(source code):

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

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

或者,将map2保持不变:

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

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