从数组数组(嵌套对象数组)中删除重复项

时间:2019-03-04 14:01:40

标签: javascript arrays

我有一个数组,其中包含另一个对象数组。我想删除此数组数组中的重复项。

var arr1 = [{
     child: [{name: "google", check: false}, {name: "yahoo", check: false}]
    },
    {
     child: [{name: "excite", check: false}, {name: "facebook", check: false}]
    },
    {
     child: [{name: "something1", check: false}, {name: "something2", check: false}]
    }
]

var arr2 = [{
     child: [{name: "google", check: true}, {name: "yahoo", check: false}]
    },
    {
     child: [{name: "excite", check: false}, {name: "facebook", check: false}]
    } 
]

var arr3 = [{
     child: [{name: "google", check: true}, {name: "yahoo", check: false}]
    },
    {
     child: [{name: "excite", check: false}, {name: "facebook", check: false}]
    },
    {
     child: [{name: "something1", check: false}, {name: "something2", check: false}]
    }
]

我想从第二个子数组中删除{name: "google", check: false},因为check: true中已经有一个同名和arr1的数组。

下面是我尝试过的东西。

function mergeAndRemoveDuplicates(arr1, arr2) {

    return arr1.map(function(child) {
        return child.some(function(children) {
            return arr2.map(function(child2) {
                return child2.some(function(children2) {
                    return children.name === children2.name &&
                        children.check === true;
                });
            })
        })
    })
}

console.log(mergeAndRemoveDuplicates(arr1, arr2));

http://jsfiddle.net/g7rvbpf3/

2 个答案:

答案 0 :(得分:3)

您可以创建一组选中的名称并递归过滤数组:

const dupes = new Set;

for(const el of arr1.concat(arr2))
  el.child = el.child.filter(el => {
     const dupe = dupes.has(el.name);
     if(el.check) dupes.add(el.name);
     return !dupe;
  });

这还将过滤arr1中的重复项,如果不希望这样,您可以使用arr1来建立集合,并过滤arr2

 const dupes = new Set;

 for(const child of arr1.flatMap(it => it.child))
   if(child.checked) dupes.add(child.name);

for(const el of arr2)
 el.child = el.child.filter(it => !dupes.has(it.name));

要获得一个数组的末尾(我想这就是“合并”的意思),您可以一个.concat到另一个。

答案 1 :(得分:2)

了解到您要基于check的新数据更新arr1中元素的arr2属性,一种可能的方法是首先在新的即将到来的namecheck值。对于这一部分,我们使用Array.reduce()。该方法的第二部分由arr1的{​​{3}}元素组成,用于保存新的更新。

var arr1 = [
    {
     child: [{name: "google", check: false}, {name: "yahoo", check: false}]
    },
    {
     child: [{name: "excite", check: false}, {name: "facebook", check: false}]
    },
    {
     child: [{name: "something1", check: false}, {name: "something2", check: false}]
    }
];

var arr2 = [
    {
     child: [{name: "google", check: true}, {name: "yahoo", check: false}]
    },
    {
     child: [{name: "excite", check: false}, {name: "facebook", check: false}]
    } 
];

let upHashTable = arr2.reduce((acc, {child}) =>
{
    child.forEach(({name, check}) => acc[name] = check);
    return acc;
}, {});

console.log("HashTable with updates: ", upHashTable);

let updated = arr1.map(({child}) =>
{
    return {child: child.map(o =>
    {
        o.check = upHashTable.hasOwnProperty(o.name) ? upHashTable[o.name] : o.check;
        return o;
    })};
});

console.log("Updated arr1 is: ", updated);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

请注意,这只会更新arr1上的值,而不会在其上插入任何新元素。