首页 文章

如何以惯用的方式在scala中创建嵌套的toSet?

提问于
浏览
7

是否有更惯用的方法将嵌套的序列序列更改为嵌套的集合?

def toNestedSet[T](tsss: Seq[Seq[Seq[T]]]): Set[Set[Set[T]]]  = 
   tsss.map(_.map(_.toSet).toSet).toSet

是否可以实现一个可以处理任何深度列表的函数?

2 回答

  • 8

    为了解决你的问题的第二部分(处理任意深度的列表),这样的事情会起作用(类型擦除有点妨碍):

    def toNestedSet(ts: Seq[Any]): Set[Any] = {
        ts.foldLeft[Set[Any]](Set())((acc, b) => b match {
            case s: Seq[_] => acc + toNestedSet(s)
            case x => acc + x
        })
      }
    

    注意:快速和肮脏 - 它的工作原理,但相当容易打破:)

    编辑:演员是多余的

  • 3

    这实际上并不是太糟糕(对于这种方法的一些额外讨论,请参阅my answer here):

    trait Setsifier[I, O] { def apply(i: I): O }
    
    object Setsifier {
      def apply[I, O](f: I => O) = new Setsifier[I, O] { def apply(i: I) = f(i) }
    
      implicit def base[I](implicit ev: I <:!< Seq[_]) = apply((_: Seq[I]).toSet)
    
      implicit def rec[I, O](implicit s: Setsifier[I, O]) =
        apply((_: Seq[I]).map(s(_)).toSet)
    }
    
    def setsify[I, O](i: I)(implicit s: Setsifier[I, O]) = s(i)
    

    然后:

    scala> println(setsify(Seq(Seq(Seq(Seq(1)), Seq(Seq(2, 3))))))
    Set(Set(Set(Set(1)), Set(Set(2, 3))))
    

    静态类型为 Set[Set[Set[Set[[Int]]]] 和所有 .

    好吧,我撒谎了一下 . 上面的 <:!< 实际上并不在标准库中 . 但是,它在_2873539中,或者您可以非常非常轻松地自己定义它:

    trait <:!<[A, B]
    
    implicit def nsub[A, B] : A <:!< B = new <:!<[A, B] {}
    implicit def nsubAmbig1[A, B >: A] : A <:!< B = sys.error("Don't call this!")
    implicit def nsubAmbig2[A, B >: A] : A <:!< B = sys.error("Don't call this!")
    

    这就是全部 .

相关问题