2

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

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

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

4

2 回答 2

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——,同时它的作用就像 amap通过让你指定过滤后的值的方式被收集。

所以我们可以匹配至少有一个头部元素和一个任意大小的尾部的尾部,然后看看在那个尾部是否存在一个元素是头部的倍数。我在这里为匹配情况使用了一个守卫,所以匹配是一个双重过滤器。首先,尾部必须是非空的,其次必须有多个。倍数意味着模数为零。如果大小写匹配,则返回已验证的 head 元素。

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

于 2013-03-31T21:17:51.490 回答
2

一个更“明确”的 - 如果 tail 有多个 head,则在 case 中累积元素:

(1 to 10).tails.foldLeft(List[Int]())((acc, tl) => tl match {
  case h +: t if (t.exists(_ % h == 0)) => h :: acc
  case _ => acc
}).reverse
于 2013-03-31T23:22:15.327 回答