【问题标题】:Merging objects which contain nested Map objects合并包含嵌套 Map 对象的对象
【发布时间】:2016-07-13 08:28:51
【问题描述】:

我有多个要递归合并的 javascript 对象。 这些对象有一些我在合并时添加在一起的数字属性。 这些对象也有一些Map 属性。以下是我的对象在开发者控制台中的外观示例:

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 对象的值,以便将所有匹配键的数量加在一起。

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

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

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

【问题讨论】:

  • 我为您解释的内容创建了一个 jsFiddle jsfiddle.net/assvfk2b/5,但我不确定您合并地图对象是什么意思,请您编辑 jsFiddle 并告诉我您到底需要什么。
  • 我更新了小提琴以显示我正在使用的实际数据结构。它利用了 javascript 中的 Map 对象。

标签: javascript merge lodash


【解决方案1】:

我想出了一个有效的合并功能。没有我希望的那么优雅,但在这里发帖以防其他人对此感到困惑。

唯一的缺点是它不像我想要的那样通用。我认为需要进行更改才能很好地处理不同类型的结构和递归复杂性。

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

【讨论】:

    【解决方案2】:

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

    因为地图是可迭代的,实际上有一种非常简单的方法可以合并它们:

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

    要通过将它们合并在一起来处理冲突值,一种选择是使用我为此目的编写的big-m 库中的mapCollectInto 函数 (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()
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多