具有条件

时间:2018-04-21 18:18:13

标签: scala list recursion combinations

所以,它非常直接,我有一个嵌套列表的列表,如下所示:

List(
*list1* List(List("n1", "n3"), List("n1", "n4"), List("n3", "n4")), 
*list2* List(List("n2"), List("n3"), List("n4"))
)

我想用 list2 的列表来分发 list1 的列表,如下所示:

List(
List(List(n1, n3), List(n2)), 
List(List(n1, n4), List(n2)), 
List(List(n3, n4), List(n2)), 
List(List(n1, n3), List(n3)), 
List(List(n1, n4), List(n3)), 
List(List(n3, n4), List(n3)), 
List(List(n1, n3), List(n4)), 
List(List(n1, n4), List(n4)), 
List(List(n3, n4), List(n4))
)

这可以通过以下功能完成:

def combinationList[T](ls:List[List[T]]):List[List[T]] = ls match {
  case Nil => Nil::Nil
  case head :: tail => val rec = combinationList[T](tail)
    rec.flatMap(r => head.map(t => t::r))
}

问题是,我想添加一个条件,我只在没有重复的地方分发列表,结果将是:

List(
List(List(n1, n3), List(n2)), 
List(List(n1, n4), List(n2)), 
List(List(n3, n4), List(n2)),  
List(List(n1, n4), List(n3)),  
List(List(n1, n3), List(n4)), 
)

我最接近的是在映射之前添加过滤器包含,但我仍然无法得到结果,如下所示:

def combinationList[T](ls:List[List[T]]):List[List[T]] = ls match {
  case Nil => Nil::Nil
  case head :: tail => val rec = combinationList[T](tail)
    rec.flatMap(r => head.filter(x => !r.contains(x)).map(t => t::r))
}

问题在于我认为它将整个列表与单个元素进行比较。有什么想法吗?

编辑:我需要忽略函数中的重复项。我知道可以对信息进行后期处理并删除重复信息,但这不是我想要的。

2 个答案:

答案 0 :(得分:1)

您需要进一步分解一个级别来检查项目的存在,最简单的形式可以如下:

def combinationList[T](ls:List[List[List[T]]]) : List[List[List[T]]] = ls match {
    case head :: tail :: Nil =>
      for {
        hl <- head
        tl <- tail
        if !tl.forall(te => hl.contains(te))
      } yield List(hl, tl)
  }

它假设输入列表有2个子列表。我不确定以通用方式拥有3个或更多子列表的期望是什么,这完全取决于你进一步递归。

答案 1 :(得分:0)

使用当前的返回类型,您可能需要再次匹配&#34;查看&#34;列表。可能会做的事情:

def combinationList[T](ls:List[List[T]]):List[List[T]] = ls match {
    case Nil => Nil::Nil
    case head :: tail => val rec = combinationList[T](tail)
        rec.flatMap(r => head.filter {
            case xx: List[_] => {
                val combined = (xx.map(List(_)) ++ r)
                combined.distinct == combined
        }
  }.map(t => t::r))
}