Scala中成对的惯用展平

Scala中成对的惯用展平,scala,Scala,我有一个函数,它将类型a的值映射到一对(Seq[B],Seq[C])。我想将函数应用于a序列,并返回一对展平的Seq[B]和Seq[C]。以下是代码片段: val a: Seq[A] val mapped: Seq[(Seq[B], Seq[C])] = a.map(f) val (b, c) = mapped.unzip val bc: (Seq[B], Seq[C]) = (b.flatten, c.flatten) 这个解决方案是可以接受的,但是有没有更惯用的方法呢?我想了解一下理解

我有一个函数,它将类型a的值映射到一对(Seq[B],Seq[C])。我想将函数应用于a序列,并返回一对展平的Seq[B]和Seq[C]。以下是代码片段:

val a: Seq[A] 
val mapped: Seq[(Seq[B], Seq[C])] = a.map(f)

val (b, c) = mapped.unzip
val bc: (Seq[B], Seq[C]) = (b.flatten, c.flatten)

这个解决方案是可以接受的,但是有没有更惯用的方法呢?我想了解一下理解或平面图,但我看不出如何将它们应用到这两个方面。

我不觉得您的代码特别不习惯,但下面是我要写的。请注意,我不相信我的代码比你的好,我只是一个折叠式的爱好者

// For testing purposes only, replace with your own code.
val b = List((List(1, 2), List(5, 6)), (List(3, 4), List(7, 8)))

val (l, r) = b.foldLeft((List[Int](), List[Int]())) {(acc, a) =>
  (acc._1 ::: a._1, acc._2 ::: a._2)
}

// Prints 'List(1, 2, 3, 4)'
println(l)

// Prints 'List(5, 6, 7, 8)'
println(r)

无形状2.0.0-M1
,因此您可以:

实际上,应该可以自动将多态方法转换为多态函数,但此代码不起作用:

def flatten[T](s: Seq[Seq[T]]) = s.flatten
l.unzip.map(flatten _)
//<console>:31: error: type mismatch;
// found   : Seq[T]
// required: Seq[Seq[T]]
//              l.unzip.map(flatten _)
//                          ^
def展平[T](s:Seq[Seq[T]])=s.flant
l、 解压地图(展平)
//:31:错误:类型不匹配;
//发现:Seq[T]
//必填项:Seq[Seq[T]]
//l.unzip.map(展平)
//                          ^

对于
Tuple2
,我可能会使用
幺半群
,对于
列表
(通过its发挥作用)我可能会使用
可折叠
实例

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> val a = List(11,222,3333,44444,555555)
a: List[Int] = List(11, 222, 3333, 44444, 555555)

scala> def f(a: Int): (List[String], List[Int]) = (a.toString.tails.toList, a.toString.tails.toList.map(_.size))
f: (a: Int)(List[String], List[Int])

scala> val mapped = a map f
mapped: List[(List[String], List[Int])] = List((List(11, 1, ""),List(2, 1, 0)), (List(222, 22, 2, ""),List(3, 2, 1, 0)), (List(3333, 333, 33, 3, ""),List(4, 3, 2, 1, 0)), (List(44444, 4444, 444, 44, 4, ""),List(5, 4, 3, 2, 1, 0)), (List(555555, 55555, 5555, 555, 55, 5, ""),List(6, 5, 4, 3, 2, 1, 0)))

scala> mapped.suml
res1: (List[String], List[Int]) = (List(11, 1, "", 222, 22, 2, "", 3333, 333, 33, 3, "", 44444, 4444, 444, 44, 4, "", 555555, 55555, 5555, 555, 55, 5, ""),List(2, 1, 0, 3, 2, 1, 0, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0, 6, 5, 4, 3, 2, 1, 0))
UPD:如果您真的想要
Seq
,以下是您需要在范围内具备的功能,以使其正常工作:

implicit val isoTraverse: IsomorphismTraverse[Seq, List] = new IsomorphismTraverse[Seq, List] {
  def G = Traverse[List]
  def iso = new IsoFunctorTemplate[Seq, List] {
    def to[A](sa: Seq[A]): List[A] = sa.toList
    def from[A](la: List[A]): Seq[A] = la.toSeq
  }
}

相关问题:+1。这是一个巧妙的问题。感觉应该有一个更干净的解决方案,但我想不出一个现成的解决方案。我曾经认为scala代码的惯用性意味着清晰(你看,这可能就是在Scala中混合OOP和FP习惯用法的原因——有时候用OOP风格编写的代码很简单,有时候用FP编写的代码很简单,你总是可以选择最清晰的一个)。鉴于此,我会使用OP的解决方案,而不是你的解决方案。“习惯于思考”-你的定义改变了吗?我想知道你的新定义是什么。我同意OP的代码比我的更清晰-我发现我的代码非常清晰,但我花了过去几周的时间用Scala的练习解决函数编程问题,这很可能影响了我的大脑。我仍然这样认为(用英语时态表示我的迷失方向):-)哇!这很聪明!但只适用于列表和向量。据我所知,
Seq
@senia没有
Monoid
实例。好吧,所需的实例可以通过派生。这里有一个。虽然不能保证这些派生实例是合法的。但他们说编程不是数学,所以谁在乎呢!
implicit val isoTraverse: IsomorphismTraverse[Seq, List] = new IsomorphismTraverse[Seq, List] {
  def G = Traverse[List]
  def iso = new IsoFunctorTemplate[Seq, List] {
    def to[A](sa: Seq[A]): List[A] = sa.toList
    def from[A](la: List[A]): Seq[A] = la.toSeq
  }
}