scala:选项元组上的复杂 flatMap
scala: complicated flatMap on a tuple of Options
我的数据类型是:List[(Option[Set[Long]], Option[Set[(Long, Long)]])]
(即一个 2 元组选项的列表,一个用于一组 Long,一个用于一组 2 元组的 Long)。例如:
val l = List((Option(Set(1L, 2L, 3L)), Option(Set((4L, 5L), (6L, 7L)))))
我希望将此列表平面映射为 List[Set[Long]]
类型,这样第二个选项的第一个元素中的每一个都将连接到具有第一个选项的新集合。所以这里想要的结果是:
List(Set(1L, 2L, 3L, 4L), Set(1L, 2L, 3L, 6L))
这适用于以下代码:
l.flatMap {
case(setOpt1, setOpt2) =>
val set1 = setOpt1.getOrElse(Set[Long]());
val set2 = setOpt2.getOrElse(Set[(Long, Long)]());
set2.map(k => set1 ++ Set(k._1))
}
当第二个选项为 None
和第一个选项 "exists" 时,情节变粗,例如:
val l = List((Option(Set(1L, 2L, 3L)), None))
假设我无法避免这种情况。在这种情况下,我想按原样获得第一个集合:
List(Set(1L, 2L, 3L))
但是,使用与上面相同的代码,set2
值变成一个空集合,而 map
在这种情况下没有任何意义,我会得到一个空列表:
res60: List[scala.collection.immutable.Set[Long]] = List()
那么,我该怎么做呢?最好优雅:)
您可以添加 case 语句来处理 Option
的每个组合
def g(l:List[(Option[Set[Long]], Option[Set[(Long, Long)]])]) = l.flatMap{
case (Some(single), None) =>
List(single)
case (Some(single), Some(tuple)) =>
tuple.map(k => single ++ Set(k._1))
case (None, Some(tuple)) =>
tuple.map(k => Set(k._1))
case (None, None) =>
List()
}
这会产生您期望的结果。这是我 运行:
的所有测试
val l1 = List((Option(Set(1L, 2L, 3L)), Option(Set((4L, 5L), (6L, 7L)))))
g(l1)
res0: List[Set[Long]] = List(Set(1, 2, 3, 4), Set(1, 2, 3, 6))
val l2 = List((Option(Set(1L, 2L, 3L)), None))
g(l2)
res1: List[Set[Long]] = List(Set(1, 2, 3))
val l3 = List((None, Option(Set((4L, 5L), (6L, 7L)))))
g(l3)
res2: List[Set[Long]] = List(Set(4), Set(6))
val l4 = List((None, None))
g(l4)
res3: List[Set[Long]] = List()
我的数据类型是:List[(Option[Set[Long]], Option[Set[(Long, Long)]])]
(即一个 2 元组选项的列表,一个用于一组 Long,一个用于一组 2 元组的 Long)。例如:
val l = List((Option(Set(1L, 2L, 3L)), Option(Set((4L, 5L), (6L, 7L)))))
我希望将此列表平面映射为 List[Set[Long]]
类型,这样第二个选项的第一个元素中的每一个都将连接到具有第一个选项的新集合。所以这里想要的结果是:
List(Set(1L, 2L, 3L, 4L), Set(1L, 2L, 3L, 6L))
这适用于以下代码:
l.flatMap {
case(setOpt1, setOpt2) =>
val set1 = setOpt1.getOrElse(Set[Long]());
val set2 = setOpt2.getOrElse(Set[(Long, Long)]());
set2.map(k => set1 ++ Set(k._1))
}
当第二个选项为 None
和第一个选项 "exists" 时,情节变粗,例如:
val l = List((Option(Set(1L, 2L, 3L)), None))
假设我无法避免这种情况。在这种情况下,我想按原样获得第一个集合:
List(Set(1L, 2L, 3L))
但是,使用与上面相同的代码,set2
值变成一个空集合,而 map
在这种情况下没有任何意义,我会得到一个空列表:
res60: List[scala.collection.immutable.Set[Long]] = List()
那么,我该怎么做呢?最好优雅:)
您可以添加 case 语句来处理 Option
def g(l:List[(Option[Set[Long]], Option[Set[(Long, Long)]])]) = l.flatMap{
case (Some(single), None) =>
List(single)
case (Some(single), Some(tuple)) =>
tuple.map(k => single ++ Set(k._1))
case (None, Some(tuple)) =>
tuple.map(k => Set(k._1))
case (None, None) =>
List()
}
这会产生您期望的结果。这是我 运行:
的所有测试val l1 = List((Option(Set(1L, 2L, 3L)), Option(Set((4L, 5L), (6L, 7L)))))
g(l1)
res0: List[Set[Long]] = List(Set(1, 2, 3, 4), Set(1, 2, 3, 6))
val l2 = List((Option(Set(1L, 2L, 3L)), None))
g(l2)
res1: List[Set[Long]] = List(Set(1, 2, 3))
val l3 = List((None, Option(Set((4L, 5L), (6L, 7L)))))
g(l3)
res2: List[Set[Long]] = List(Set(4), Set(6))
val l4 = List((None, None))
g(l4)
res3: List[Set[Long]] = List()