如何使用依赖于多个元素的条件筛选列表

时间:2013-03-31 21:10:49

标签: scala functional-programming

给定列表L我想保留一个元素L(i),如果它至少存在一个值j > i,那么L(j)L(i)的倍数,否则{... 1}应该被丢弃。

通过命令式编程范式来做到这一点非常简单,但我想用函数式编程来做到这一点。

可以使用L(i)方法吗?如果是这样,如何写条件(即filter函数的参数)?否则,我该怎么办?

2 个答案:

答案 0 :(得分:4)

例如:

val l = (1 to 100)
l.tails.collect { case (head +: tail) if tail.exists(_ % head == 0) => head } .toList

tail生成一个迭代器,在每个步骤中返回输入减去一个元素,例如

(1 to 10).tails.foreach(println)

给出

Vector(1, 2, 3, 4)
Vector(2, 3, 4)
Vector(3, 4)
Vector(4)
Vector()

您可以将这些“尾巴”视为要应用过滤器的头部元素,以及用于确定是否保留头部的尾部。

collect方法在这里很有用,因为它需要部分函数,​​所以你只需要指定实际保留类似值filter - 的情况,同时它通过让您指定如何收集过滤后的值来充当map

所以我们可以匹配至少有一个头部元素和任何大小的尾部的尾部,然后看看在那个尾部是否存在一个元素是头部的倍数。我在这里使用 guard 作为匹配大小写,因此匹配是双重过滤器。首先,尾部必须是非空的,其次必须是多个。倍数意味着模数为零。如果案例匹配,只需返回经过验证的头元素。

最后,由于没有特定类型的注释,collect将只返回另一个迭代器,我们将结果转换为toList的列表。

答案 1 :(得分:2)

更“明确”的一个 - 如果尾部有多个头部,则会累积元素:

(1 to 10).tails.foldLeft(List[Int]())((acc, tl) => tl match {
  case h +: t if (t.exists(_ % h == 0)) => h :: acc
  case _ => acc
}).reverse