【问题标题】:Return the same collection type after performing multiple operations on the collection对集合执行多次操作后返回相同的集合类型
【发布时间】:2017-05-22 09:46:51
【问题描述】:

仅当对集合进行一次操作时,使用隐式 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

是否有允许编译的更改?

【问题讨论】:

    标签: scala generics collections


    【解决方案1】:

    你已经引入了隐含的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()
    }
    

    顺便说一句,在这种情况下,maps 可以折叠。

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

    【讨论】:

    • 我是否理解正确,广义的解决方案如下?首先,进行所有所需的操作以获得所需的结果集合。然后,在构建器上使用+= 迭代所需的结果以附加每个项目。最后返回builderresult()产生的结果。
    • 是的,我相信这是大致的大纲。查看TraversableLike source 中的一些简单直接示例的方式。
    • 很遗憾CanBuildFrom 不能像只执行一个操作时那样隐式使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 2013-08-25
    • 1970-01-01
    • 2011-07-09
    • 2014-01-21
    相关资源
    最近更新 更多