[英]Vanilla Javascript merge JSON array objects into nested array if match a common value
我找不到与我要解决的问题相同的解决方案。 如果重复,请提供指向解决方案的链接。
使用原始Javascript,合并具有共同值的对象数组。 我有一个JSON文件,它将创建以下javascript对象(我无法更改原始结构)。 请注意,每个对象将具有不同的嵌套名称和嵌套值。 但是,通用值是名称[0]
var data = [
{
name: [
'Data 1', // common value
'1 Jan, 2019', // same value therefore not overwrite/merge
'hotfix dec'
],
value: [
'hotfix1.fsfix',
'hotfix1.txt'
]
},
{
name: [
'Data 1', // common value
'1 Jan, 2019' // same value therefore not overwrite/merge
],
value: 'data1.jar'
},
{
name: [
'Data 2',
'1 Feb, 2019'
],
value: 'data2.fsfix'
},
{
name: [
'Data 2',
'1 Feb, 2019'
],
value: 'data2.jar'
},
{
name: [
'Data 3',
'1 Mar, 2018'
],
value: 'data3.fsfix'
}
]
期望输出将合并具有相同名称[0]的嵌套对象。
var data = [
{
name: [
'Data 1', // common value
'1 Jan, 2019', // same value therefore not overwrite/merge
'hotfix dec'
],
value: [
'data1.fsfix',
'data1.txt',
'data1.jar' // This was added after the merge
]
},
{
name: [
'Data 2',
'1 Feb, 2019'
],
value: [
'data2.fsfix',
'data2.jar' // This was added after the merge
]
},
{
name: [
'Data 3',
'1 Mar, 2018'
],
value: 'data3.fsfix'
}
]
使用这种新的合并结构,我将创建一个函数来循环每个数组集。 提前致谢
您可以使用地图通过名字输入数据。 然后将数据填充到对应Map值内的value
属性中,还收集name
数组中的所有额外值(除了前两个条目之外),最后提取Map值。
这适用于线性时间复杂度:
var data = [{name: ['Data 1', '1 Jan, 2019', 'hotfix dec'],value: ['hotfix1.fsfix','hotfix1.txt']},{name: ['Data 1', '1 Jan, 2019'],value: 'data1.jar'},{name: ['Data 2','1 Feb, 2019'],value: 'data2.fsfix'},{name: ['Data 2','1 Feb, 2019'],value: 'data2.jar'},{name: ['Data 3','1 Mar, 2018'],value: 'data3.fsfix'}]; const map = new Map(data.map(o => [o.name[0], { name: o.name.slice(0,2), value: [] }])); data.forEach(o => map.get(o.name[0]).value.push(...[].concat(o.value))); data.forEach(o => map.get(o.name[0]).name.push(...o.name.slice(2))); const result = Array.from(map.values(), o => o.value.length === 1 ? { ...o, value: o.value[0] } : o); console.log(result);
传递给Array.from
的回调函数是一个映射函数。 仅需要将只有一个字符串的值数组转换为该字符串。 如果这不是必需的,则可以省略该回调,而只需执行Array.from(map.values())
。
使用某些Array方法,我认为您可以完成这项工作(下面的未经测试的代码,但是我认为它应该做您想要的事情):
// Merge matching entries by pushing values from matching objects to each other
data = data.map(entry => {
let matchingObjects = data.filter(match => {
return match.name[0] === entry.name[0];
});
matchingObjects.forEach(match => {
if (match !== entry) {
var flatValue = [entry.value].flat();
entry.value = flatValue.push.apply(flatValue, [match.value].flat());
}
});
});
// Remove duplicates by filtering out all but the first entry of each name[0]
data = data.filter((entry, index) => {
return index === data.findIndex(match => {
return match.name[0] === entry.name[0];
});
});
您还可以使用reduce
和map
创建所需的结果。 我认为总体而言,这是一个非常强大的组合。
const data = [{name: ['Data 1', '1 Jan, 2019', 'hotfix dec'],value: ['hotfix1.fsfix','hotfix1.txt']},{name: ['Data 1', '1 Jan, 2019'],value: 'data1.jar'},{name: ['Data 2','1 Feb, 2019'],value: 'data2.fsfix'},{name: ['Data 2','1 Feb, 2019'],value: 'data2.jar'},{name: ['Data 3','1 Mar, 2018'],value: 'data3.fsfix'}];
const dataMap = data.reduce((acc, curr)=>{
id = curr.name[0];
acc[id] = acc[id] || {
name: [],
value: []
};
const value = Array.isArray(curr.value) ? curr.value : [curr.value]
acc[id].name = [...acc[id].name, ...curr.name.filter((i)=>acc[id].name.indexOf(i)===-1)]
acc[id].value = [...acc[id].value, ...value.filter((i)=>acc[id].value.indexOf(i)===-1)]
return acc
},{})
const result = Object.keys(dataMap).map(key=> {
const d = dataMap[key];
d.value = d.value.length===1 ? d.value[0] : d.value
return d;
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.