1

假设我有 3 个元组序列,看起来像这样:

Seq("m1" -> 1, "m2" -> 2)
Seq("m3" -> 3, "m4" -> 4)
Seq("m5" -> 5, "m2" -> 6)

我想映射这些并返回 3 条新记录,如下所示:

Seq("m1" -> Some(1), "m2" -> Some(2), "m3" -> None, "m4" -> None, "m5" -> None)
Seq("m1" -> None, "m2" -> None, "m3" -> Some(3), "m4" -> Some(4), "m5" -> None)
Seq("m1" -> None, "m2" -> Some(6), "m3" -> None, "m4" -> None, "m5" -> Some(5))

我正在寻找的新集合包含来自原始列表的不同键集的键,以及Some(v)基于None相应原始序列是否包含元组的值。

我设法从原始列表中取出钥匙:

case class SiteReading(val site: String, val measures: Seq[(String, Double)])
val xs = getSomeSiteReadingsFromSomewhere()
val keys = xs.flatMap(_.measures.map(t => t._1)).distinct

我现在计划再次浏览整个列表,通过查看当前值和唯一键集来生成一个新列表。我想知道集合框架中是否有一些漂亮的东西可以使它更清洁和更易于处理?也许是免费的?

4

4 回答 4

1

这是一种方法。映射键并查询每个映射以查看它是否包含键。

制作一组键来迭代。

scala> val ms = (1 to 5).map(i => "m" + i)
ms: scala.collection.immutable.IndexedSeq[String] = Vector(m1, m2, m3, m4, m5)

三元组序列

scala> val s1 = Seq("m1" -> 1, "m2" -> 2).toMap
s1: scala.collection.immutable.Map[String,Int] =  Map(m1 -> 1, m2 -> 2)

scala> val s2 = Seq("m3" -> 3, "m4" -> 4).toMap
s2: scala.collection.immutable.Map[String,Int] = Map(m3 -> 3, m4 -> 4)

scala> val s3 = Seq("m5" -> 5, "m2" -> 6).toMap
s3: s3: scala.collection.immutable.Map[String,Int] = Map(m5 -> 5, m2 -> 6)

mapSeq钥匙在每个Set,并尝试得到钥匙。

scala> ms.map(m => m -> s1.get(m))
res19: scala.collection.immutable.IndexedSeq[(String, Option[Int])] = 
Vector((m1,Some(1)), (m2,Some(2)), (m3,None), (m4,None), (m5,None))

scala> ms.map(m => m -> s2.get(m))
res20: scala.collection.immutable.IndexedSeq[(String, Option[Int])] = 
Vector((m1,None), (m2,None), (m3,Some(3)), (m4,Some(4)), (m5,None))

scala> ms.map(m => m -> s3.get(m))
res21: scala.collection.immutable.IndexedSeq[(String, Option[Int])] = 
Vector((m1,None), (m2,Some(6)), (m3,None), (m4,None), (m5,Some(5)))
于 2013-10-07T23:36:35.383 回答
1
val s1 = Seq("m1" -> 1, "m2" -> 2)
val s2 = Seq("m3" -> 3, "m4" -> 4)
val s3 = Seq("m5" -> 5, "m2" -> 6)
val ss = Seq(s1, s2, s3)
def foo(xss: Seq[Seq[(String,Int)]]): Seq[Seq[(String,Option[Int])]] = {
  val keys = xss.flatMap(_.map(_._1)).toSet
  xss.map{ xs => 
    val found = xs.map{ case (s,i) => (s, Some(i)) }
    val missing = (keys diff xs.map(_._1).toSet).map(x => (x, None)).toSeq
    (found ++ missing).sortBy(_._1)
  }
}

scala> foo(ss).foreach(println)
List((m1,Some(1)), (m2,Some(2)), (m3,None), (m4,None), (m5,None))
List((m1,None), (m2,None), (m3,Some(3)), (m4,Some(4)), (m5,None))
List((m1,None), (m2,Some(6)), (m3,None), (m4,None), (m5,Some(5)))
于 2013-10-07T23:38:03.087 回答
1

我喜欢 Rex Kerr 的回答。我评论说这个解决方案也很有效,并且可能更加清晰和简洁。

def denormalize(xss: Seq[Seq[(String, Double)]]): Seq[Map[String, Option[Double]]] = {
  val keys = xss.flatMap(_.map(_._1)).distinct.sorted
  val base = keys.map(_ -> None).toMap[String, Option[Double]]
  xss.map(base ++ _.map(t => t._1 -> Option(t._2)))
}

它和一套一样有效。我不确定哪个表现更好。我可能会测试两者。

于 2013-10-08T16:27:42.180 回答
0

这是我的解决方案:

val s1 = Seq("m1" -> 1, "m2" -> 2)
val s2 = Seq("m3" -> 3, "m4" -> 4)
val s3 = Seq("m5" -> 5, "m2" -> 6)

def process(ss: Seq[(String, Int)]*): Seq[Seq[(String, Option[Int])]] = {
  val asMap = ss map (_.toMap)
  val keys = asMap.flatMap(_.keys).sorted
  for(m <- asMap) yield keys.map(k => k -> m.get(k)) 
}

val Seq(r1, r2, r3) = process(s1, s2, s3)

结果:

r1: Seq[(String, Option[Int])] = ArrayBuffer((m1,Some(1)), (m2,Some(2)), (m2,Some(2)), (m3,None), (m4,None), (m5,None))
r2: Seq[(String, Option[Int])] = ArrayBuffer((m1,None), (m2,None), (m2,None), (m3,Some(3)), (m4,Some(4)), (m5,None))
r3: Seq[(String, Option[Int])] = ArrayBuffer((m1,None), (m2,Some(6)), (m2,Some(6)), (m3,None), (m4,None), (m5,Some(5)))
于 2013-10-08T02:18:41.300 回答