从一个列表中提取不在另一个列表中的元素

Ech*_*cho 4 scala

简单地说,我有两个列表,我需要提取添加到其中一个的新元素.我有以下内容

val x = List(1,2,3)
val y = List(1,2,4)

val existing :List[Int]= x.map(xInstance => {
      if (!y.exists(yInstance =>
        yInstance == xInstance))
        xInstance
    })

Result :existing: List[AnyVal] = List((), (), 3)
Run Code Online (Sandbox Code Playgroud)

我需要以最低成本删除除数字之外的所有其他元素.

ret*_*nym 17

选择合适的数据结构,生活变得更加容易.

scala> x.toSet -- y
res1: scala.collection.immutable.Set[Int] = Set(3)
Run Code Online (Sandbox Code Playgroud)

还要注意:

if (condition) expr1
Run Code Online (Sandbox Code Playgroud)

是速记:

if (condition) expr1 else ()
Run Code Online (Sandbox Code Playgroud)

使用此结果,通常具有静态类型AnyAnyVal几乎总是错误.它只适用于副作用:

if (condition) buffer += 1
if (condition) sys.error("boom!")
Run Code Online (Sandbox Code Playgroud)


Lui*_*hys 14

如果你没有重复的元素并且你不关心订单,那么retronym的解决方案是可以的.但是你没有表明是这样的.

因此,转换y为集合(非x)可能最有效.我们只需要遍历列表一次,并且对该集合具有快速的O(log(n))访问权限.

所有你需要的是

x filterNot y.toSet
// res1: List[Int] = List(3)
Run Code Online (Sandbox Code Playgroud)

编辑:

此外,还有一个更简单的内置方法:

x diff y
Run Code Online (Sandbox Code Playgroud)

(我看了一下实现;它看起来非常有效,使用HashMap计算出现次数.)

  • 尼斯.读者不应该"Set [T]`实现`T => Boolean`. (5认同)

Joa*_*son 5

简单的方法是使用过滤器,因此没有什么可以删除;

val existing :List[Int] = 
  x.filter(xInstance => !y.exists(yInstance => yInstance == xInstance))
Run Code Online (Sandbox Code Playgroud)

  • 注意:`exists`和`filter`是'O(N)`,所以这里的组合是'O(N ^ 2)` (4认同)
  • 同样的东西,但更漂亮:`x.filterNot(y.contains)` (4认同)