Is there a more idiomatic way to change a nested sequence of sequences into a nested set of sets?
def toNestedSet[T](tsss: Seq[Seq[Seq[T]]]): Set[Set[Set[T]]] =
tsss.map(_.map(_.toSet).toSet).toSet
Is it possible to implement a function which would work with lists of any depth?
This actually isn't too bad at all (see my answer here to a similar question for some additional discussion of this approach):
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)
And then:
scala> println(setsify(Seq(Seq(Seq(Seq(1)), Seq(Seq(2, 3))))))
Set(Set(Set(Set(1)), Set(Set(2, 3))))
Statically typed as a Set[Set[Set[Set[[Int]]]]
and all.
Well, I lied a little bit. The <:!<
above isn't actually in the standard library. It is in Shapeless, though, or you can very, very easily define it yourself:
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!")
And that's really all.
To address the second part of your question (processing a list of arbitrary depth), something like this would work (type erasure gets in the way a bit):
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
})
}
Note: quick and dirty -- it works, but fairly easy to break :)
Edit: The cast was redundant
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With