Scala 元组序列上的平面映射

Scala 元组序列上的平面映射,scala,collections,Scala,Collections,给定以下代码: def flatMap2[A, B, C](s:Seq[(A, B)])(f: B => Seq[C]) : Seq[(A, C)] = s.flatMap { case (a, b) => f(b).map((a, _)) } 有没有更好的编码方法(scalaz中可能存在某种东西) 你能帮我找个更好的名字吗 是否有更通用的抽象使用(Iterable,TraversableOnce)?问题可能不清楚,此时我想说: //s1:Seq[(A,B)],f:B=>C v

给定以下代码:

def flatMap2[A, B, C](s:Seq[(A, B)])(f: B => Seq[C]) : Seq[(A, C)] =
  s.flatMap { case (a, b) => f(b).map((a, _)) }
有没有更好的编码方法(scalaz中可能存在某种东西)

你能帮我找个更好的名字吗


是否有更通用的抽象使用(
Iterable
TraversableOnce
)?

问题可能不清楚,此时我想说:

//s1:Seq[(A,B)],f:B=>C
val s2:Seq[(A,C)]=s1.map((A,b)=>A->f(b))
这个怎么样:

import scala.collection.GenTraversable
import scala.collection.GenTraversableLike
import scala.collection.GenTraversableOnce
import scala.collection.generic.CanBuildFrom

implicit class WithMapFlatMapValues[A, B, Repr <: GenTraversable[(A, B)]](val self: GenTraversableLike[(A, B), Repr]) extends AnyVal {
  def flatMapValues[C, That](f: B => GenTraversableOnce[C])(implicit bf: CanBuildFrom[Repr, (A, C), That]) = {
    self.flatMap { case (a, b) => f(b).toIterator.map(a -> _) } 
  }
}
您也可以使用迭代器来实现这一点(因此您已经涵盖了TraversableOnce的所有内容):

带有MapFlatMapValueSiter[A,B](val self:Iterator[(A,B)]的隐式类扩展了AnyVal{
def flatMapValues[C](f:B=>GenTraversableOnce[C])={
对于{(a,b)1,“b”->2.flatMapValues(Seq.fill(_)(“x”))
//i1:迭代器[(字符串,字符串)]=非空迭代器
i1.1矢量
//res6:Vector[(String,String)]=向量((a,x),(b,x),(b,x))
看起来好一点:

def flatMap2[A, B, C](List[(A, B)])(f: B => Seq[C]) : List[(A, C)] =
   for((a,b) <- s; bb <- f(b)) yield a -> bb
ListMap
在此处保存原始顺序。
mapValues
返回
ListMap
上的视图,这也将保留顺序

Scalaz的幺半群可以帮助您将元素添加到此类映射中:

yourListMap |+| ListMap(key -> List(value))

scala>  val map = ListMap(2 -> List("a"), 1 -> List("c"))
map: scala.collection.immutable.ListMap[Int,List[String]] = Map(2 -> List(a), 1 -> List(c))

scala> (map: Map[Int,List[String]]) |+| ListMap(1 -> List("b"))
res11: scala.collection.immutable.Map[Int,List[String]] = Map(2 -> List(a), 1 -> List(c, b))

您可以使用
Seq
而不是
List
,但这样您就不会隐式转换到。

这不会编译;即使修改为编译,它也不会实现所需的行为。有一种方法可以只使用一个impl?为什么不使用可遍历而不是(gentraversableone,GenTraversableLike)?Ex:flatMapValues[A,B](s:Traversable[(A,B)]){def flatMapValues[C](f:B=>TraversableOnce[C]):Traversable[(A,C)]=s.flatMap{case(A,B)=>f(B).map((A,u))}使用GenTraversable意味着它将处理比可遍历更多的内容。使用GenTraversableLike/CanBuildFrom使其类似于Scala的内置集合:生成调用它的相同类型。您编写的小版本将始终返回可遍历类型的对象,而不会返回更具体的类型。
def flatMap2[A, B, C](List[(A, B)])(f: B => Seq[C]) : List[(A, C)] =
   for((a,b) <- s; bb <- f(b)) yield a -> bb
def flatMap2[A, B, C](s: ListMap[A, List[B]])(f: B => List[C]) : Map[A, List[C]] = 
   s.mapValues(_.flatMap(f))

scala> flatMap2(ListMap(2 -> List("a"), 1 -> List("c")))(x => List(x + "a"))
res4: scala.collection.immutable.Map[Int,List[String]] = Map(2 -> List(aa), 1 -> List(ca))
yourListMap |+| ListMap(key -> List(value))

scala>  val map = ListMap(2 -> List("a"), 1 -> List("c"))
map: scala.collection.immutable.ListMap[Int,List[String]] = Map(2 -> List(a), 1 -> List(c))

scala> (map: Map[Int,List[String]]) |+| ListMap(1 -> List("b"))
res11: scala.collection.immutable.Map[Int,List[String]] = Map(2 -> List(a), 1 -> List(c, b))