我知道我可以这样做:
scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)
scala> val b = List(2,4)
b: List[Int] = List(2, 4)
scala> a.filterNot(b.toSet)
res0: List[Int] = List(1, 3)
但是我想根据整数键选择集合的元素,如下所示:
case class N (p: Int , q: Int)
val x = List(N(1,100), N(2,200), N(3,300))
val y = List(2,4)
val z = .... ?
Z // want Z to be ((N1,100), (N3,300)) after removing the items of type N with 'p'
// matching any item in list y.
我知道有一种方法可以做到以下几点使得上面破解的代码工作:
val z = x.filterNot(e => y.contains(e.p))
但这看起来非常低效。还有更好的方法吗?
答案 0 :(得分:4)
只做
val z = y.toSet
x.filterNot {z.contains(_.p)}
那是线性的。
答案 1 :(得分:2)
contains
的问题在于搜索将是线性搜索,您正在查看O(N^2)
解决方案(如果数据集不大,仍然可以)
无论如何,一个简单的解决方案是使用二进制搜索来获得O(NlnN)
解决方案。您可以轻松地从列表中将val y转换为Array,然后使用java的二进制搜索方法。
scala> case class N(p: Int, q: Int)
defined class N
scala> val x = List(N(1, 100), N(2, 200), N(3, 300))
x: List[N] = List(N(1,100), N(2,200), N(3,300))
scala> val y = Array(2, 4) // Using Array directly.
y: Array[Int] = Array(2, 4)
scala> val z = x.filterNot(e => java.util.Arrays.binarySearch(y, e.p) >= 0)
z: List[N] = List(N(1,100), N(3,300))