Scala不可变数组过滤条件

时间:2018-07-23 23:42:48

标签: scala filter adjacency-matrix

我正在处理项目中的邻接矩阵,因此需要安全地移除边缘。

我正在从事的项目以下列方式使用矩阵: Map[Agent, Array[Edge]]。我想使用Array.filter函数删除有问题的边缘。我这样做是为了避免使用索引或zipWithIndex

在矩阵中添加四个“ agent”并添加两个无向边后,这就是我的矩阵:

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

您会看到边缘是(A1,A2)和(A3,A4)。

要去除边缘(A1,A2),我正在使用它:

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

但是,这将删除空条目(按预期)。这是使用上述技术去除边缘后矩阵的样子:

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

空条目的作用是重要,因为它允许我快速在其正确位置插入新边。我正在寻找一种过滤出单个边缘的解决方案。

简单地做的问题:

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

我正在对空条目进行操作,这会导致NullPointerException(显然)。我正在寻找解决方案。

重申一下,我想使用可能为null或不为null的每个边的属性进行过滤。有没有一种方法可以实现“如果为空则跳过”

感谢您的帮助和建议。

2 个答案:

答案 0 :(得分:1)

使用Option而不是使用null元素会更好。 Scala Optionnull的更强大且类型安全的替代方案。

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,

您可以filterOption,它将仅测试Some的值并跳过None的值。

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

答案 1 :(得分:0)

我认为您错过了真正的问题。

处理null的方式很好。问题是您正在尝试使用filter,它会从您的集合中删除元素,从而将其缩短。

如果您想用null替换集合中的某些元素,那么不变的方法是使用map

var arr = Array(null, 1.1, null, null)
arr = arr.map(e => if (e == 1.1) null else e)
println(arr.toList)  // List(null, null, null, null)

但是,请注意一些事项。

  1. scala中的数组是可变的。意思是,您可以执行以下操作:

    arr(edgeIndex) = null
    

    这会将您的边缘替换为null。

  2. Scala具有不变的序列Vector。如果使用它而不是数组,则可以具有不变性和索引更新,如下所示:

    var vec = Vector(null, 1.1, null, null)
    vec = vec.updated(edgeIndex, null)
    println(vec) // Vector(null, null, null, null)