2014-07-09 44 views
1

我有两种不同形状的数据结构,它们来自两个不同的API。数据是JSON格式,语言是JavaScript。合并两种不同形状的数据结构

阵列1:

[ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" }, 
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" }, 
        { "html" : "some_html", "name" : "TASK_NAME_2" } ] }, 
    { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" }, 
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" }, 
        { "html" : "some_html", "name" : "TASK_NAME_4" } ] }] 

阵列2:

[ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" }, 
     { "name" : "TASK_NAME_2", "status" : "OPEN" } ], 
    [ { "name" : "TASK_NAME_3", "status" : "OPEN" }, 
     { "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ] 

工具提示字段的来自阵列1的元素包含相同的 “名称” S作为阵列2的元件我怎样才能优雅地将数组2中的“状态”合并到数组1中的工具提示中?

我认为镜头可能是正确的答案,但我不确定,因为我从来没有使用过它们。

我知道一些方法,我可以解决它使用嵌套迭代和更新数组1.我理想的是寻找一种方法,不会修改现有的数据结构。

+0

所以我认为它会看起来沿线。 [array1,array2] .zip.map(get_from_array_2(_lens?),insert_into_array_2(_lens?)) – sumek

+0

您谈论'zip'ping。你保证两个数组的结构是一样的吗?或者你需要通过'name'找到它们吗? – Bergi

+1

这两个数组的结构是一样的。 – sumek

回答

1

这是有点复杂,但它应该为你工作

array2.forEach(function(tooltips){ 
    tooltips.forEach(function(tooltip){ 
     for (var i = 0; i < array1.length; i++) { 
      for (var j = 0; j < array1[i].tooltips.length; j++) { 
       var arr1Tooltip = array1[i].tooltips[j]; 
       if(arr1Tooltip.name == tooltip.name) 
        arr1Tooltip.status = tooltip.status; 
      }; 
     };   
    }); 
}); 

console.log(JSON.stringify(array1)); 
+0

这是一个很好的工作解决方案,与我目前实施的解决方案类似。虽然我不是那种人。我会更新我的问题。 – sumek

+0

为什么你把'forEach'循环与''for''循环混淆?此外,这*修改了现有的数据结构,这是OP不需要的。 – Bergi

+0

@Bergi OP更新了问题。看看以前的评论。我为前一个做过。 – Mritunjay

0

这可能大大超过设计的,而不是非常有效的,但你可以做到这一点,与使用递归函数this JSFiddle。我太累了,不能用聪明的方式来做。

var arr1 = [ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" }, 
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" }, 
        { "html" : "some_html", "name" : "TASK_NAME_2" } ] }, 
    { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" }, 
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" }, 
        { "html" : "some_html", "name" : "TASK_NAME_4" } ] }]; 

var arr2 = [ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" }, 
     { "name" : "TASK_NAME_2", "status" : "OPEN" } ], 
    [ { "name" : "TASK_NAME_3", "status" : "OPEN" }, 
     { "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ]; 

var findStatus = function(name, searchArray) { 
    var r = ''; 
    if (typeof searchArray === 'object') { 
     if ("name" in searchArray && "status" in searchArray) { 
      if (searchArray.name == name) { 
       return searchArray.status; 
      } else { 
       return ''; 
      } 
     } else { 
      for (var i in searchArray) { 
       r = findStatus(name, searchArray[i]); 
       if (r != '') { 
        return r; 
       } 
      } 
     } 
    } 
    return ''; 
}; 

var updateStatus = function(arrToUpdate, arrWithStatus) { 
    var copy = $.extend(true, {}, arrToUpdate); 
    var r = ''; 
    if (typeof copy === 'object') { 
     if ("name" in copy) { 
      r = findStatus(copy.name, arrWithStatus); 
      if (r != '') { 
       copy.status = r; 
      } 
     } else { 
      for (var i in copy) { 
       copy[i] = updateStatus(copy[i], arrWithStatus); 
      } 
     } 
    } 
    return copy; 
}; 

var arr3 = updateStatus(arr1, arr2); // Final combined array 

我加入了var copy = $.extend(true, {}, arrToUpdate);行,以便它会做一个深拷贝,而不是修改原始数组,因此,它需要jQuery的。

0

由于你的数据结构嵌套,你将需要两个zip.map/zipWith S:

zip(array1, array2).map(function([obj, tooltips]) { // ES6 destructuring syntax 
    return { 
     document: obj.document, 
     tooltips: zip(obj.tooltips, tooltips).map(function([tooltip, extender]) { 
      return { 
       html: tooltip.html, 
       name: tooltip.name, 
       status: extender.status 
      }; 
     }) 
    }; 
}) 

如果你不喜欢重复的对象常量结构,你或许可以用一些复印功能;例如

extend({}, document, {tooltips:…}) 
extend({}, tooltip, extender); 

你也可以使用一个镜头库像https://github.com/DrBoolean/lenseshttps://github.com/fantasyland/fantasy-lenses对于这一点,但我不知道这是否是值得的 - 上面的代码只需要强调/ lodash。

为了避开内部zipWith,你需要一个Traversal镜头(我假设你熟悉this article),但我还没有看到一个提供这样的JavaScript库。

+0

如果您不确定如何使用镜片,请选择一个图库,我将举例说明我的意思。 – Bergi

相关问题