Search code examples
scalafilteradjacency-matrix

Scala Immutable Array Filter Condition


I am working with an adjacency matrix in a project and I need to remove an edge safely.

The project I am working on uses the matrix in the following way: Map[Agent, Array[Edge]]. I would like to use the Array.filter function to remove the edge in question. I am doing this to avoid using indexing or zipWithIndex.

After adding four "agent"s to the matrix and adding two undirected edges this is what my matrix looks like:

A1: null, 1.1, null, null, 
A2: 1.1, null, null, null, 
A3: null, null, null, 1.2, 
A4: null, null, 1.2, null, 

As you can see the edges are (A1, A2) and (A3, A4).

To remove edge (A1, A2) I am using this:

map = map.updated(a1, map(a2).filter(e => e != null && e.toAgent != a2))

However, this is removing the null entries (as expected). This is what my matrix looks like after removing an edge using the above technique:

A1: 1.1, 
A2: 
A3: null, null, null, 1.2, 
A4: null, null, 1.2, null, 

The role of null entries is important because it allows for me to quickly insert new edges in their correct location. I am looking for a solution to filtering out a single edge.

The problem with simply doing:

map = map.updated(a1, map(a2).filter(e => e.toAgent != a2))

Is that I am operating on null entries which causes a NullPointerException (obviously). I am looking for a solution to this.

To reiterate, I want to filter using an attribute of each edge that may or may not be null. Is there a way to implement a type of "skip if null"?

Thanks for your help and advice.


Solution

  • You would be better off using Option rather than having null elements. Scala Option is a much more powerful and type-safe alternative to null.

    A1: None,      Some(1.1), None,      None, 
    A2: Some(1.1), None,      None,      None, 
    A3: None,      None,      None,      Some(1.2), 
    A4: None,      None,      Some(1.2), None,
    

    You can filter an Option and it will only test Some values and skip None values.

    map = map.updated(a1, map(a2).map(_.filter(_.toAgent == a2)))