Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:筛选元组列表以获取非空列表_Scala_Scala Cats - Fatal编程技术网

Scala:筛选元组列表以获取非空列表

Scala:筛选元组列表以获取非空列表,scala,scala-cats,Scala,Scala Cats,我有一个类型为list[(a,list[B])]的列表。我想将此结构展平并获得: NonEmptyList[A]包含与非空列表[B]对应的所有A 所有这些Bs组合在一起:NonEmptyList[B] 例如,我想获得选项[(非空列表[A],非空列表[B])]。最简洁的方法是什么。未经测试,但使用注释中的定义,应该可以: for { a <- NonEmptyList.fromList(list.collect{ case (a, _::_) => a }) b <-

我有一个类型为
list[(a,list[B])]
的列表。我想将此结构展平并获得:

  • NonEmptyList[A]
    包含与非空
    列表[B]
    对应的所有
    A

  • 所有这些
    B
    s组合在一起:
    NonEmptyList[B]


例如,我想获得
选项[(非空列表[A],非空列表[B])]
。最简洁的方法是什么。

未经测试,但使用注释中的定义,应该可以:

for {
  a <- NonEmptyList.fromList(list.collect{ case (a, _::_) => a })
  b <- NonEmptyList.fromList(list.flatMap(_._2))
} yield (a, b)
另一个版本可能是

(listA, listB) match {
  case (_::_, _::_) =>
    Some(NonEmptyList(listA), NonEmptyList(listB))
  case _ =>
    None
}

您可以使用tail递归函数迭代列表,但它可能不是很简洁,但可能比第二个解决方案快,因为它只在列表上迭代一次

def flat[A,B](list: List[(A, List[B])]): Option[(NonEmptyList[A], NonEmptyList[B])] = {

    @tailrec
    def collapse(list: List[(A, List[B])], as: List[A], bs: List[B]): (List[A], List[B]) = {
      list match {
        case (a,b) :: xs => collapse(xs, a :: as, b ++ bs)
        case Nil => (as, bs)
      }
    }

    collapse(list, Nil, Nil) match {
      case (a :: ax, b :: bx) => Some((NonEmptyList(a, ax), NonEmptyList(b, bx)))
      case _ => None
    }

}
另一个选项是使用
解压

def flat2[A,B](list: List[(A, List[B])]) = list.unzip match {
   case (as,bs) => (as, bs.flatten)  match {
      case (a :: ax, b :: bx) => Some((NonEmptyList(a, ax), NonEmptyList(b, bx)))
      case _ => None
   }
}
结果:

flat(List((1, List("a", "b")), (2, List("a", "c")), (3, List("d", "e")), (4, List("x", "y"))))
//Some((NonEmptyList(4, 3, 2, 1),NonEmptyList(x, y, d, e, a, c, a, b)))
flat(List((1, List()), (2, List("a"))))
//Some((NonEmptyList(2, 1),NonEmptyList(a)))
flat(List((1, List()), (2, List())))
//None
flat(List())
//None

NonEmptyList的构造函数采用头和尾。或者,它还有一个fromList函数,可以为您提供一个选项[NonEmptyList]Ahh。。。顶部的配方看起来很棒。:)我不认为你在应用这个测试:“
NonEmptyList[A]
由所有与非空
列表[B]
相对应的
A
组成”是的,老实说,我不明白。这是否意味着A也应该包含B中的值?@KrzysztofAtłasik假设A是一个人,B是一辆汽车。原始列表是映射到他们拥有的汽车的人员列表。我想得到一份所有司机和他们拥有的所有汽车的清单。你能在你的问题中添加一个示例测试用例吗?例如,假设您的输入是
(List((1,List(“a”,“b”),(2,List(“a”,“c”),(3,List(“d”,“e”),(4,List(“x”,“y”))
)。你期望的产量是多少?订单重要吗?@Tim,在这种情况下,应该返回
None
<代码>平面(列表((1,列表(),(2,列表(2)))
的计算结果为
None
flat(List((1, List("a", "b")), (2, List("a", "c")), (3, List("d", "e")), (4, List("x", "y"))))
//Some((NonEmptyList(4, 3, 2, 1),NonEmptyList(x, y, d, e, a, c, a, b)))
flat(List((1, List()), (2, List("a"))))
//Some((NonEmptyList(2, 1),NonEmptyList(a)))
flat(List((1, List()), (2, List())))
//None
flat(List())
//None