Scala "belongsTo" function

10 浏览
0 Comments

Scala "belongsTo" function

我经常遇到这种筛选的情况:

allPeople
  .filter(person => englishPeopleIds contains person.id)

如果有一种"belongsTo"函数可以做到以下操作,将会更方便并且代码更易读:

allPeople
  .filter(_.id belongsTo englishPeopleIds)

belongsTo函数将具有以下行为(但将成为元素的方法):

def belongsTo[T](element: T, list: List[T]): Boolean = list contains element

您是否知道Scala中是否已经实现了这样的函数?

0
0 Comments

Scala中的belongsTo函数问题的出现原因是,在Scala中没有内置的belongsTo函数。然而,可以使用隐式类或Dotty中的扩展方法来实现类似的功能。

对于隐式类的解决方法,可以使用以下代码:

implicit class BelongsTo[T](private val t: T) extends AnyVal {
  def belongsTo(s: Seq[T]): Boolean = s.contains(t)
  def belongsTo(s: Set[T]): Boolean = s(t)
}

对于Dotty中的解决方法,可以使用以下代码:

extension [T](t: T):
  def belongsTo(s: Seq[T]): Boolean = s.contains(t)
  def belongsTo(s: Set[T]): Boolean = s(t)

然而,有人认为这个问题不值得解决。为了避免实例化的成本,可以将隐式类也设置为AnyVal。此外,将其应用于任何集合而不仅仅是列表可能是值得考虑的。

然而,某些情况下在Iterable中缺少contains方法,并且在Set、Seq和Map中的实现方式也不同。对此,有人认为在集合上进行抽象是非常奇怪的。

最后,某些情况下了一个相关的问题,即Scala 2.8中的集合库是否是一份自杀的遗嘱。

0
0 Comments

问题的出现原因是需要定义一个Scala的"belongsTo"函数,该函数可以判断一个元素是否属于一个集合。解决方法是使用隐式类定义一个名为ElementOf的类,该类包含一个名为∈的方法,该方法接受一个元素作为参数,并返回一个布尔值,表示该元素是否属于集合。该方法内部使用contains或exists方法进行元素的判断。根据集合的类型的不同,可以定义多个隐式类实现不同的∈方法。

首先,可以在Sequential Collections上定义一个右结合的运算符,代码如下:

implicit class ElementOf[A](l: Seq[A]) {
  def ∈: (a: A): Boolean = l contains a
}

使用数学符号∈来表示元素属于,该符号属于Scala的操作符字符。使用该方法可以进行如下调用:

allPeople filter (_.id ∈: englishPeopleIds)

如果还需要支持Set和Map类型的集合,则可以使用Iterable#exists方法进行定义,代码如下:

implicit class ElementOf[A](cc: Iterable[A]) {
  def ∈: (a: A): Boolean = cc exists (_ == a)
}

请注意,这两种方法都是使用隐式类进行定义的,因此在使用时需要导入相应的隐式类。

最后,如果还需要实现一个∩方法来计算两个集合的交集,可以继续定义一个名为Intersection的隐式类,代码如下:

implicit class Intersection[A](val coll: Iterable[A]) {
  def ∩(other: Iterable[A]): Unit = {
    coll.filter(_ ∈ other)
  }
}

以上就是解决Scala "belongsTo"函数的问题的方法。

0