如何在集合上减少(),将集合本身​​保留在 Scala 中?

How to reduce() on a collection keeping the collection itself in Scala?

我只需要减少集合中的元素,但我想在结果中保留集合。

scala> List("a","b","c").reduce(_+_)
res0: String = abc

我想得到

scala> List("a","b","c").someSortOfReduce(_+_)
res0: List[String] = List(abc)

scala> Seq("a","b","c").someSortOfReduce(_+_)
res1: Seq[String] = Seq(abc)

由于你想要的集合和原始集合不共享任何条目,你可以将 reduce 的结果包装在你想要的任何东西中。

Seq(original.reduce(_+_))

我自己找到了解决方案

val list = List("a","b","c")
list.companion(list.reduce(_+_))

使用companion方法

def red[T](a: Iterable[T], f: (T,T) => T) = a.companion(a.reduce(f))

已编辑

如果您需要保留静态类型,一个选项是使用 asInstanceOf

implicit class Reduce[T, C[T] <: Iterable[T]](s: C[T]) {
  def someSortOfReduce(f: (T, T) => T): C[T] = s.companion(s.reduce(f)).asInstanceOf[C[T]]
}
val list = List(1, 2, 3).someSortOfReduce(_ + _)  // list: List[Int] = List(6)
val set = Set(1, 2, 3).someSortOfReduce(_ + _)    // set: Set[Int] = Set(6)

或模式匹配

implicit class Reduce[T, C[T] <: Iterable[T]](s: C[T]) {
  def someSortOfReduce(f: (T, T) => T): C[T] = s.companion(s.reduce(f)) match {
    case a: C[T] => a
  }
}

这是一种方法(可能不是最优雅的,但是,嘿,它有效):

import collection.generic._
def reduceAsCollection[E,C[_]](s: C[E])(f: (E,E) => E)(implicit cbf: CanBuildFrom[Nothing, E, C[E]], e: C[E] <:< TraversableOnce[E]): C[E] = {
  (cbf() += s.reduce(f)).result
}

以及强制性 REPL 测试:

scala> reduceAsCollection(List("a","b","c"))(_+_)
res14: List[String] = List(abc)

scala> reduceAsCollection(Seq("a","b","c"))(_+_)
res15: Seq[String] = Vector(abc)

如您所见,不仅生成的集合具有适当的运行时类型,而且还保留了静态类型(给 Seq 返回 Seq,给 List, 获得 List 回报)。