SMILET
在此提交中,“充实”Scala集合要比Rex给出的出色答案要容易得多。对于简单的情况,它可能看起来像这样,import scala.collection.generic.{ CanBuildFrom, FromRepr, HasElem }import language.implicitConversionsclass FilterMapImpl[A, Repr](val r : Repr)(implicit hasElem : HasElem[Repr, A]) { def filterMap[B, That](f : A => Option[B]) (implicit cbf : CanBuildFrom[Repr, B, That]) : That = r.flatMap(f(_).toSeq)}implicit def filterMap[Repr : FromRepr](r : Repr) = new FilterMapImpl(r)它filterMap为所有GenTraversableLikes 增加了一个“相同的结果类型” ,scala> val l = List(1, 2, 3, 4, 5)l: List[Int] = List(1, 2, 3, 4, 5)scala> l.filterMap(i => if(i % 2 == 0) Some(i) else None)res0: List[Int] = List(2, 4)scala> val a = Array(1, 2, 3, 4, 5)a: Array[Int] = Array(1, 2, 3, 4, 5)scala> a.filterMap(i => if(i % 2 == 0) Some(i) else None)res1: Array[Int] = Array(2, 4)scala> val s = "Hello World"s: String = Hello Worldscala> s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)res2: String = HW对于问题的例子,解决方案现在看起来像,class GroupIdenticalImpl[A, Repr : FromRepr](val r: Repr) (implicit hasElem : HasElem[Repr, A]) { def groupIdentical[That](implicit cbf: CanBuildFrom[Repr,Repr,That]): That = { val builder = cbf(r) def group(r: Repr) : Unit = { val first = r.head val (same, rest) = r.span(_ == first) builder += same if(!rest.isEmpty) group(rest) } if(!r.isEmpty) group(r) builder.result }}implicit def groupIdentical[Repr : FromRepr](r: Repr) = new GroupIdenticalImpl(r)示例REPL会话,scala> val l = List(1, 1, 2, 2, 3, 3, 1, 1)l: List[Int] = List(1, 1, 2, 2, 3, 3, 1, 1)scala> l.groupIdenticalres0: List[List[Int]] = List(List(1, 1),List(2, 2),List(3, 3),List(1, 1))scala> val a = Array(1, 1, 2, 2, 3, 3, 1, 1)a: Array[Int] = Array(1, 1, 2, 2, 3, 3, 1, 1)scala> a.groupIdenticalres1: Array[Array[Int]] = Array(Array(1, 1),Array(2, 2),Array(3, 3),Array(1, 1))scala> val s = "11223311"s: String = 11223311scala> s.groupIdenticalres2: scala.collection.immutable.IndexedSeq[String] = Vector(11, 22, 33, 11)同样,请注意,已经观察到相同的结果类型原则,其方式与groupIdentical直接定义的方式完全相同GenTraversableLike。
撒科打诨
在这个提交中,魔术咒语与Miles给出的出色答案略有不同。以下作品,但它是规范的吗?我希望其中一个经典能够纠正它。(或者说,大炮,大枪之一。)如果视图绑定是上限,则会丢失对Array和String的应用程序。如果绑定是GenTraversableLike或TraversableLike似乎并不重要; 但IsTraversableLike为您提供了GenTraversableLike。import language.implicitConversionsimport scala.collection.{ GenTraversable=>GT, GenTraversableLike=>GTL, TraversableLike=>TL }import scala.collection.generic.{ CanBuildFrom=>CBF, IsTraversableLike=>ITL }class GroupIdenticalImpl[A, R <% GTL[_,R]](val r: GTL[A,R]) { def groupIdentical[That](implicit cbf: CBF[R, R, That]): That = { val builder = cbf(r.repr) def group(r: GTL[_,R]) { val first = r.head val (same, rest) = r.span(_ == first) builder += same if (!rest.isEmpty) group(rest) } if (!r.isEmpty) group(r) builder.result }}implicit def groupIdentical[A, R <% GTL[_,R]](r: R)(implicit fr: ITL[R]): GroupIdenticalImpl[fr.A, R] = new GroupIdenticalImpl(fr conversion r)只有一种方法可以让有九条生命的猫皮肤美化。这个版本说,一旦我的源转换为GenTraversableLike,只要我可以从GenTraversable构建结果,就这样做。我对我的旧Repr不感兴趣。class GroupIdenticalImpl[A, R](val r: GTL[A,R]) { def groupIdentical[That](implicit cbf: CBF[GT[A], GT[A], That]): That = { val builder = cbf(r.toTraversable) def group(r: GT[A]) { val first = r.head val (same, rest) = r.span(_ == first) builder += same if (!rest.isEmpty) group(rest) } if (!r.isEmpty) group(r.toTraversable) builder.result }}implicit def groupIdentical[A, R](r: R)(implicit fr: ITL[R]): GroupIdenticalImpl[fr.A, R] = new GroupIdenticalImpl(fr conversion r)第一次尝试包括将Repr转换为GenTraversableLike。import language.implicitConversionsimport scala.collection.{ GenTraversableLike }import scala.collection.generic.{ CanBuildFrom, IsTraversableLike }type GT[A, B] = GenTraversableLike[A, B]type CBF[A, B, C] = CanBuildFrom[A, B, C]type ITL[A] = IsTraversableLike[A]class FilterMapImpl[A, Repr](val r: GenTraversableLike[A, Repr]) { def filterMap[B, That](f: A => Option[B])(implicit cbf : CanBuildFrom[Repr, B, That]): That = r.flatMap(f(_).toSeq)} implicit def filterMap[A, Repr](r: Repr)(implicit fr: ITL[Repr]): FilterMapImpl[fr.A, Repr] = new FilterMapImpl(fr conversion r)class GroupIdenticalImpl[A, R](val r: GT[A,R])(implicit fr: ITL[R]) { def groupIdentical[That](implicit cbf: CBF[R, R, That]): That = { val builder = cbf(r.repr) def group(r0: R) { val r = fr conversion r0 val first = r.head val (same, other) = r.span(_ == first) builder += same val rest = fr conversion other if (!rest.isEmpty) group(rest.repr) } if (!r.isEmpty) group(r.repr) builder.result } } implicit def groupIdentical[A, R](r: R)(implicit fr: ITL[R]): GroupIdenticalImpl[fr.A, R] = new GroupIdenticalImpl(fr conversion r)