Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.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_Folding_Fold - Fatal编程技术网

在Scala中,当有时两个元素不应该变成一个元素时,如何折叠?

在Scala中,当有时两个元素不应该变成一个元素时,如何折叠?,scala,folding,fold,Scala,Folding,Fold,我有一个成对的列表,它们表示具有开始索引和结束索引的行。类型为(Int,Int)是两个整数的元组 例如,现在我想把任何相互接触的线条连接在一起 列表((1,5)、(6,10)、(12,20))应该转换为列表((1,10)、(12,20)),因为第(1,5)行接触第(6,10)行。只有接触线连接在一起形成一条线 我的第一个想法是在列表中使用foldleft,问题是foldleft需要将两个元素转换为一个元素,最终只输出一个(Int,Int) 第二个想法是我编写的递归解决方案,但这似乎不是最好或最简

我有一个成对的列表,它们表示具有开始索引和结束索引的行。类型为(Int,Int)是两个整数的元组

例如,现在我想把任何相互接触的线条连接在一起

列表((1,5)、(6,10)、(12,20))应该转换为列表((1,10)、(12,20)),因为第(1,5)行接触第(6,10)行。只有接触线连接在一起形成一条线

我的第一个想法是在列表中使用foldleft,问题是foldleft需要将两个元素转换为一个元素,最终只输出一个(Int,Int)

第二个想法是我编写的递归解决方案,但这似乎不是最好或最简单的想法。我们获取两个元素,有时输出一个或两个元素的想法似乎应该应用于许多情况,就像foldleft所做的那样

有没有解决这个问题的通用方法、模式或库


一条直线位于一维平面上,它不是x,y点。(Int,Int)是一维平面上的起点和终点

澄清触摸的定义。列表中的所有行都不重叠,这是一个先决条件,即(1,3)和(2,4)不能存在于列表中,因为它们重叠

(1,3)、(4,5)可以存在于列表中,因为它们不重叠

(1,3),(4,5)确实接触,因为3和4之间的距离正好为1

对于问题((1,5)、(6,10)、(6,12)、(13,15))中给出的列表,这是一个无效列表,因为(6,10)、(6,12)重叠


请注意,这是我在写这个问题之前的工作代码,你可以看到它不太好。我只是在用我的知识构建递归函数,它构建一个结果并返回结果

  private def joinAtoB(a: LineLike, b: LineLike): LineLike = {
    newFunction(a.start, b.end)
  }

  private def joinTouchingLines(a: LineLike, b: LineLike): Option[LineLike] = {
    if ((a.end + 1) == b.start)
      Some(joinAtoB(a, b))
    else
      None
  }

  @tailrec
  def joinLinesRec(list: List[LineLike], result: List[LineLike] = List[LineLike]())
                     :List[LineLike] = {
    list match {
      case Nil => result
      case item :: Nil => item :: result

      case first :: second :: rest => {
        val joined = joinTouchingLines(first, second)
        val prepend = joined match {
          case None => List(first, second)
          case Some(joinedItem) => List(joinedItem)
        }
        joinLinesRec(rest, prepend ::: result)
      }
    }
  }

使用foldLeft执行此操作很简单,但如果在重叠或接触时取出规则的零件,则更简单:

def touching(fp: (Int, Int), sp: (Int, Int)) = 
  if (fp._2 >= sp._1) sys.error("Overlap " + fp + " and " + sp) 
  else if (fp._2 == sp._1 - 1) true 
  else false
然后,您可以决定何时只追加,何时扩展最后一对:

list.foldLeft(List[(Int,Int)]()){
  (l, p) => 
    if (l.isEmpty || !touching(l.head, p)) p :: l
    else (l.head._1, p._2) :: l.tail
}.reverse

您可以使用模拟cons(
)的二进制函数使用
foldRight
而不是
foldLeft
,除非相邻元素接触:

def combine(x: (Int, Int), lst: List[(Int, Int)]) = (x, lst) match {
  case (_, Nil) => List(x)
  case ((a, b), (c, d) :: rest) => if (c == b+1)
                                     (a, d) :: rest
                                   else
                                     (a, b) :: lst
}

所以两端都是包容的(因为(1,5)接触(6,10))?您想对多个可能的变体做什么,即((1,5)、(6,10)、(6,12)、(13,15))?您到底想最小化列表中剩余的元素数吗?不管怎样,看起来你们必须对列表进行排序,然后运行递归(或动态规划)算法。我认为第(1,3)行和第(2,4)行也很重要@菲尔,如果我错了,请纠正我。(如果所有行都是不相交的,这也足以得到唯一的解决方案。)
foldLeft
也可以返回列表。你只需要构造它。@pedrofura,那么也许foldLeft可以生成一个列表[(Int,Int)]?我不知道你是怎么想的。@Phil:这是经典的FP/逻辑编程练习,到目前为止,我已经用六种语言解决了:)但是你自己弄明白这一点的关键是看看与列表构造的联系,foldRight做得很好。例如,
map
可以实现为一个
foldRight
,在对元素应用一个函数后,它会在元素前面加上前缀。我很不情愿地赢得了这场胜利,我发现相对于命令式编程和可变状态,我很难理解这一点。也许某个图书馆会使这篇文章更容易写和理解。@larsmans(+1)优雅的回答,在类似的情况下帮助了我