2015-09-17 36 views
-1

我有类似这样的两个JavaScript对象:合并两个对象,而不会覆盖

"Object 1": { 
    "a": { 
     "1": "test 1", 
     "2": "test 2" 
    }, 
    "b": { 
     "3": "test 3", 
     "4": "test 4" 
    }, 
} 

"Object 2": { 
    "a": { 
     "1": "test 5", 
     "2": "test 6" 
    }, 
    "b": { 
     "3": "test 7", 
     "4": "test 8" 
    }, 
} 

两者之间唯一的区别是非常最深层次的价值观。我想合并它们,因此生成的对象如下所示:

"Object 4": { 
    "a": { 
     "1": ["test 1", "test 5"], 
     "2": ["test 2", "test 6"] 
    }, 
    "b": { 
     "3": ["test 3", "test 7"], 
     "4": ["test 4", "test 8"] 
    }, 
} 

基本上我只是想将最深的值合并到列表中。任何人都可以帮忙吗?

编辑:我的最终目标是要吐出这些值出到表像这样:

<table> 
    <tr> 
     <td>test 1</td> 
     <td test 5</td> 
    </tr> 
    <tr> 
     <td>test 2</td> 
     <td test 6</td> 
    </tr> 
    <tr> 
     <td>test 3</td> 
     <td test 7</td> 
    </tr> 
    <tr> 
     <td>test 4</td> 
     <td test 8</td> 
    </tr> 
</table> 

如果你知道一个更好的方式来完成这件事,请让我知道!

+0

如果能在源头被清理到更合理的结构将首先做有 – charlietfl

+0

我的问题是我正在阅读两个单独的JSON文件进行产品比较,据我所知这个我我可以让他们结构化的唯一方法。我无法合并这两个文件,因为我可能需要比较集合中的任何两个文件。 – SilverSerpent

回答

4

var o = { 
 
    1: { 
 
    "a": { "1": "test 1", "2": "test 2" }, 
 
    "b": { "3": "test 3", "4": "test 4" }, 
 
    }, 2: { 
 
    "a": { "1": "test 5", "2": "test 6" }, 
 
    "b": { "3": "test 7", "4": "test 8" }, 
 
    } 
 
} 
 

 
function mergeObject (base, toMerge) { 
 
    // loop through the keys in the item to be merged (`toMerge`) 
 
    for (var key in toMerge) { 
 
    // if `base[key]` is not already an object, set it as one 
 
    base[key] = base[key] || {} 
 
    // look through the keys in `toMerge[key]` 
 
    for (var k in toMerge[key]) { 
 
     // if the base already has an array at `base[key][k]` 
 
     if (Array.isArray(base[key][k])) { 
 
     // then push the current element 
 
     base[key][k].push(toMerge[key][k]) 
 
     } else { 
 
     // otherwise, create an array and set `toMerge[key][k]` as the first element 
 
     base[key][k] = [toMerge[key][k]] 
 
     } 
 
    } 
 
    } 
 
    return base 
 
} 
 

 
function merge (o1, o2) { 
 
    return mergeObject(mergeObject({}, o1), o2) 
 
} 
 

 
document.write(JSON.stringify(merge(o[1], o[2])))

3

我会用underscore.js。这个例程将适用于任何级别的两棵树的叶值,而不仅仅是深度的第二级。

function is_object_only(v) 
 
{ 
 
    //_.isObject() returns true for functions and Arrays. But this predicate only returns true for objects 
 
    return _.isObject(v) && !_.isFunction(v) && !_.isArray(v) 
 
} 
 

 
function concat_leaf_values(obj_1, obj_2) 
 
{ 
 
    var result = {} 
 
    var all_keys = _.union(_.keys(obj_1), _.keys(obj_2)) 
 
    _.each(all_keys, function(key) 
 
    { 
 
    var new_val 
 
    var v1 = obj_1[key] 
 
    var v2 = obj_2[key] 
 
    if(is_object_only(v1) && is_object_only(v2)) 
 
    { 
 
     new_val = concat_leaf_values(v1, v2) //recurse 
 
    } 
 
    else 
 
    { 
 
     new_val = _.compact([].concat(v1).concat(v2)) 
 
     // if either v1 or v2 is an array, they will be concatenated on, not nested. 
 
     // and we are stripping any undefined/null values in case v1 or v2 don't exist. 
 
     // if you intentionally want arrays with null/undefined in your tree, then this clause 
 
     // should be changed 
 
    } 
 
    result[key] = new_val 
 
    }) 
 
    return result 
 
} 
 

 
//concat_leaf_values({a:{a:1, b:2}, b:5}, {a:{a:10, b:20}, b:50}) => {"a":{"a":[1,10],"b":[2,20]},"b":[5,50]}
<script src="http://underscorejs.org/underscore-min.js"></script>

+0

JavaScript约定比'snake_case'更喜欢'camelCase'。它会让你的代码更难阅读,尤其是因为你使用了下划线库,这让我在每个'_'处看两次。 – royhowie

+0

太好了,谢谢你的回答,我也会通过这个工作。 – SilverSerpent

0

你可以使用下划线map

下面是摘录:

_.map(object1, function(val, key){ 
    if(object2[key] != undefined) { 
    _.map(val, function(val1, key1){ 
     if(object2[key][key1] != undefined){ 
      val[key1] = val1 + "," + object2[key][key1]; 
     } 
    }); 
    } 
});