Scala "belongsTo" function
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中是否已经实现了这样的函数?
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中的集合库是否是一份自杀的遗嘱。
问题的出现原因是需要定义一个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"函数的问题的方法。