2014-07-09 43 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

相關問題