根据scala中另一个List的值筛选列表

时间:2018-02-23 12:58:12

标签: scala

说我有

val l1 = List(1,2,3,4)
val l2 = List(True,False,False,True)

我想过滤l1中与l2

中的True元素对应的元素

我做了以下事情:

type Predicate[T] = T => Boolean
def filterXbasedOnY[A, B](X: List[A], Y: List[B], p: Predicate[B]): List[A] = {
    {
      for {i <- 0 until Y.size if p(Y(i))} yield X(i)
    }.toList
}

通过调用

工作正常
val result = filterXbasedOnY(l1, l2, (b:Boolean) => b)

但这是实现这一目标的最佳方式吗?

3 个答案:

答案 0 :(得分:2)

List(1, 2, 3, 4).zip(List(true, false, false, true)).filter(_._2).map(_._1)

正如@ C4stor所建议的那样,如果想要将过滤的使用范围扩大到不同类型,我认为我们可以降低复杂度(我在下面使用toMatch:B来简化,但Predicate仍然可以使用):

def filter[A, B](l1: List[A], l2: List[B], toMatch: B): List[A] = {
  l1.zip(l2).filter(_._2 == toMatch).map(_._1)
}

因此,在继续使用List对象的同时,管道将是O(n)。否则,在列表上调用p(Y(i)) n次将是O(n2)。

正如@ C4stor所指出的那样,并且你的解决方案已经是这种情况,它处理的l1比l2短。

filter(List("1", "2", "3"), List("True", "False", "True", "False"), "True") // List(1, 3)

答案 1 :(得分:0)

我不知道这是否是最好的方式,但它至少是一个好方法:

  • 易于阅读和明确
  • 它处理l2不是布尔,它可以很容易地被固定以正确处理X比Y小一些
  • 它包含得很好并且易于测试

所提议的一个衬里都没有那些理想的属性,所以,对你们有所称,做得好!在我看来,你的解决方案实际上就是建议的一个衬里的准备版本。

顺便说一下,我可以向您推荐codereview stackexchange for codereview style questions吗?

答案 2 :(得分:0)

语法可能使其更具可读性,并且使用filterFunction意味着l2可以是它需要的任何类型。

for( (l1,l2) <- (list1 zip list2) if (filterFunction(l2))) yield l1