我有两个不同形状的数据结构来自两个不同的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中工具提示字段的元素包含相同的" name" s作为数组2的元素。如何优雅地合并" status"从数组2到数组1中的工具提示?
我认为镜头可能是正确的答案,但我不确定,因为我从未使用它们。
我知道一些方法可以使用嵌套迭代和更新数组1来解决它。我理想地寻找一种不修改现有数据结构的方法。
答案 0 :(得分: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));
答案 1 :(得分: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。
答案 2 :(得分: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/lenses或https://github.com/fantasyland/fantasy-lenses这样的镜头库,但我不确定这是否值得付出 - 上面的代码只需要下划线/ lodash。
要绕过内部zipWith
,你需要一个Traversal
镜头(我假设你熟悉this article),但我还没有看到一个JavaScript库,提供这样的。