Scala 不可变数组过滤条件

Scala Immutable Array Filter Condition

我在项目中使用邻接矩阵,我需要安全地移除边。

我正在从事的项目按以下方式使用矩阵: 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 的空条目进行操作(很明显)。我正在寻找解决方案。

重申一下,我想使用每条边的属性进行过滤,该属性可能为空,也可能不为空。有没有办法实现"skip if null"的一种类型?

感谢您的帮助和建议。

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

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

如果您想用空值替换集合中的某些元素,不可变的方法是使用 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
    

    这会将您的边替换为空值。

  2. Scala 具有不可变序列,Vector。如果你使用它而不是数组,你可以拥有不变性和索引更新,就像这样:

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

您最好使用 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,

您可以 filter 一个 Option,它只会测试 Some 个值并跳过 None 个值。

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