在对集合

时间:2017-01-07 20:00:50

标签: scala generics collections

使用隐式CanBuildFrom参数似乎只对在对集合进行一次操作时返回相同类型的集合。是否有一种简单的方法可以让更多逻辑复杂的方法返回与参数类型相同的类型?

给出以下代码:

def trimCharacters(items: Iterable[String]): Iterable[String] =
  items map (_.replaceAll("\\W", "")) map (_.replaceAll("\\w", ""))

如果将items的集合类型和返回类型都更改为子类型有效子类型Iterable,则代码仍将编译。我想概括一下,以便调用者根据提供的Iterable类型选择返回类型。

This answer utilizing CanBuildFrom接近,但只有原始的第一个map

def trimNonWordCharacters[T <: Seq[String]]
    (items: T with SeqLike[String, T])
    (implicit cbf: CanBuildFrom[T, String, T]): T =
  items map (_.replaceAll("\\W", ""))

执行第二张地图的简单行为:

def trimCharacters[T <: Seq[String]]
    (items: T with SeqLike[String, T])
    (implicit cbf: CanBuildFrom[T, String, T]): T =
  items.map(_.replaceAll("\\W", "")).map(_.replaceAll("\\w", ""))

打破编译:

type mismatch;
[error]  found   : Seq[String]
[error]  required: T

是否有允许编译的更改?

1 个答案:

答案 0 :(得分:2)

您已经隐含CanBuildFrom,但您没有使用它。

def trimCharacters[T <: Seq[String]](items: T with SeqLike[String, T]
                                   )(implicit cbf: CanBuildFrom[T, String, T]
                                   ): T = {
  val builder = cbf(items)
  builder.sizeHint(items)
  items.map(_.replaceAll("\\W","")).map(_.replaceAll("\\w","")).foreach(builder += _)
  builder.result()
}

BTW,在这种情况下,map可以折叠。

items.map(_.replaceAll("\\W", "").replaceAll("\\w", "")).foreach(builder += _)