Search code examples
javascriptd3.jsadjacency-matrix

D3.js - merge two adjacency matrices in ones with D3/JS


I want to merge 2 adjacency matrices in ones with d3.js. Just as example:

Matrix 1:

{
    "nodes":[
        {
            "id": a,
            "year": 1
        },{
            "id": b,
            "year": 1
        },
        {
            "id": c,
            "year": 1
        }
    ],
    "links":[
        {
            "source": a,
            "target": b
        },
        {
            "source": a,
            "target": c
        }
    ]
}

Matrix 2:

{
    "nodes":[
        {
            "id": a,
            "year": 2
        },{
            "id": b,
            "year": 2
        },
        {
            "id": d,
            "year": 2
        }
    ],
    "links":[
        {
            "source": a,
            "target": b
        },
        {
            "source": a,
            "target": d
        }
    ]
}

as you can see, some IDs appear in both matrices, like a and b. And I want to merge this cell in both matrices in ones and change the color of this cell. can someone give me some ideas how to solve this issue?

The result must be something like this:

{
    "nodes":[
        {
            "id": a,
            "year": 3
        },{
            "id": b,
            "year": 3
        },
        {
            "id": c,
            "year": 1
        },
                {
            "id": d,
            "year": 2
        }
    ],
    "links":[
        {
            "source": a,
            "target": b
        },
        {
            "source": a,
            "target": c
        },
        {
            "source": a,
            "target": d
        }
    ]
}


Solution

  • So, as I understood, what you need to do (merge and highlight duplicate nodes, based on duplicate adjacency, not id), you may go like that:

    • walk through combined array of links to find out unique/duplicate entries (considering reverse source/target as well)
    • walk through combined array of nodes and mark with year:3 those nodes that belong to duplicating links
    • build up resulting object of links and nodes

    const m1 = {"nodes":[{"id":'a',"year":1},{"id":'b',"year":1},{"id":'c',"year":1}],"links":[{"source":'a',"target":'b'},{"source":'a',"target":'c'}]},
          m2 = {"nodes":[{"id":'a',"year":2},{"id":'b',"year":2},{"id":'d',"year":2}],"links":[{"source":'a',"target":'b'},{"source":'a',"target":'d'}]},
          
          links = [...m1.links, ...m2.links].reduce((r,l) => {
            const dup = r.find(({source:s, target: t}) => 
              (s == l.source && t == l.target) || 
              (s == l.target && t == l.source))
            dup ? dup.dup = true : r.push(l)
            return r
          }, []),
          
          nodes = [...m1.nodes, ...m2.nodes].reduce((r,n) => {
            const dupL = links.find(l => 
              l.dup && (l.source == n.id || l.target == n.id)),
                  dupN = r.find(({id}) => id == n.id)
            !dupN && r.push({...n, ...(dupL && {year: 3})})
            return r
          }, []),
          
          mergedMatrix = {links:links.map(({dup,...rest}) => rest),nodes}
         
    console.log(mergedMatrix)
    .as-console-wrapper{min-height:100%;}