在 Javascript 中根据不重复的交集累积合并数组

Cumulatively merge arrays based on intersection without duplicates in Javascript

我有像这样聚集的数据
[[1, 2, 3], [0, 2], [2, 4], [6, 7]].
我想合并共享项目而不重复的数组。
例如,我从上述数据中寻找的结果是
[[1, 2, 3, 0, 4], [6, 7]].

我的做法是循环遍历数组,当找到交集时,将两个数组形成并集。这是我尝试过的:

let clusters = [[1, 2, 3], [0, 2], [2, 4], [6, 7]];
let len = clusters.length;
let i, j;
for (i = 0; i < len; i++)  {
  for (j = i+1; j < len; j++)  {
    if (clusters[i].filter(x => clusters[j].includes(x))) {
      clusters[i] = [...new Set([...this.clusters[i], ...this.clusters[j]])]; // this won't work
    }
  }
}

结果是clusters数组没有变化。我认为如果我能找到一种递归地 运行 联合操作的方法(当满足交集条件时),这可能会起作用。
或者也许有更好的方法?

这可能(我没有真正测试过,以此作为开始研究的想法)可行。

您实际上不需要递归,因为您只处理一个嵌套级别。如果你有一个大数据集,请注意这个不好的性能。

var a=[[1, 2, 3], [0, 2], [2, 4], [6, 7]];

function match(a,b) {
    //if you meant _at least_ one match between two elements
    for(var i=0;i<a.length;i++) if(b.indexOf(a[i])>0) return true;
    return false;
}

function combine(a,b) {
    var c=[];
    for(var i=0;i<a.length;i++) if(c.indexOf(a[i])<0) c.push(a[i]);
    for(var i=0;i<b.length;i++) if(c.indexOf(b[i])<0) c.push(b[i]);
    return c;
}

while(1) {
    var found=false;
    for(var i=0;i<a.length;i++) {
        for(var j=0;j<a.length;j++) {
            if(i==j) continue;
            //if a match is found, merge the two elements and start over
            if(match(a[i],a[j])) {
                a[i]=combine(a[i],a[j]);
                a.splice(j,1);
                found=true;
                break;
            }
        }
        if(found) break;
    }
    //repeat until no matches were found
    if(!found) break;
}

console.log(a);

您可以使用 Array.reduce 执行此操作,将数组从 clusters 推送到输出数组中的集合中,或者如果值已存在于输出中的集合之一中则合并,然后再转换回来完成后从集合到数组:

let clusters = [
  [1, 2, 3],
  [0, 2],
  [2, 4],
  [6, 7]
];

let result = clusters.reduce((c, a) => {
    for (i = 0; i < c.length; i++) {
      if (a.some(v => c[i].has(v))) {
        a.forEach(v => c[i].add(v));
        return c;
      }
    }
    c.push(new Set(a));
    return c;
  }, [])
  .map(s => Array.from(s));
console.log(result);