[英]merging two data structures of different shapes
我有两个来自两个不同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中工具提示字段的元素包含与数组2元素相同的“名称”。如何将数组2中的“状态”优雅地合并到数组1中的工具提示中?
我以为镜头可能是正确的答案,但我不确定,因为我从未使用过它们。
我知道使用嵌套迭代和更新数组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));
这可能是工程化的方式,效率不是很高,但是您可以像使用递归函数一样使用此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。
由于您的数据结构是嵌套的,因此需要两个zip.map
/ zipWith
:
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的镜头库,但是我不确定这是否值得-以上代码只需要下划线/破折号。
要绕过内部zipWith
,您需要一个Traversal
镜头(我想您对本文很熟悉),但是我还没有看到提供这种功能的JavaScript库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.