使用迭代器时类型不匹配

时间:2016-01-18 11:45:52

标签: scala

当我运行以下代码时,我收到此错误 - 类型不匹配,找到:scala.collection.immutable.IndexedSeq [Int] required:Range

我哪里出错了?

功能 -

def calcRange(i: Int, r: List[Range]):List[Range] = r match {
   case List() => List(new Range(i,i+1,1))

   case r1::rs =>
        if (r1.start-1==i) {new Range(i,r1.end,1):: rs; }

        else if(r1.end==i){new Range(r1.start,r1.end+1,1)::rs}

        else {r1::calcRange(i,rs)}
}

def recurseForRanges(l: Iterator[Int]):List[Range] = {
   var ans=List[Range]()
   while(l.hasNext){
       val cur=l.next;
       ans=calcRange(cur,ans)
    }
   ans
}

def rangify(l: Iterator[Int]):Iterator[Range] = recurseForRanges(l).toIterator

驱动程序代码

def main(args: Array[String]) {

    val x=rangify( List(1,2,3,6,7,8).toIterator ).reduce( (x,y) => x ++ y)      
/** This line gives the error -type mismatch, 
found : scala.collection.immutable.IndexedSeq[Int] required: Range */
}

1 个答案:

答案 0 :(得分:4)

您可以查看文档:

++[B](that: GenTraversableOnce[B]): IndexedSeq[B]

++返回IndexedSeq,而不是其他RangeRange不能包含“漏洞”。

解决此问题的一种方法是在缩小之前将Ranges更改为IndexedSeqs。这会使Range向上转换,以便reduce可以执行功能

(IndexedSeq[Int], IndexedSeq[Int]) => IndexedSeq[Int]

因为现在需要

(Range, Range) => Range

但是++实际上会返回IndexedSeq[Int]而不是Range,因此会出现类型错误。

val x = rangify(List(1, 2, 3, 6, 7, 8).iterator).map(_.toIndexedSeq).reduce(_ ++ _)

您也可以通过注释类型执行此类转换:

val it: Iterator[IndexedSeq[Int]] = rangify(List(1,2,3,6,7,8).iterator)
val x = it.reduce(_ ++ _)

请注意,您的代码可以简化,而不需要vars

def calcRange(r: List[Range], i: Int): List[Range] = r match {
   case Nil =>
      Range(i, i + 1) :: Nil
   case r1 :: rs =>
      if (r1.start - 1 == i)
        Range(i, r1.end) :: rs
      else if (r1.end == i) 
        Range(r1.start, r1.end + 1) :: rs
      else 
        r1 :: calcRange(rs, i)
}

def recurseForRanges(l: Iterator[Int]): List[Range] = {
   l.foldLeft(List.empty[Range])(calcRange)
}

def rangify(l: Iterator[Int]): Iterator[Range] = recurseForRanges(l).iterator

val x = rangify(List(1,2,3,6,7,8).iterator).map(_.toIndexedSeq).reduce(_ ++ _)

解释我用它做了什么:

Range有一个工厂方法,您不需要new个关键字,您不需要指定by值,因为1是默认值。 你也不需要分号。

您在recurseForRanges中所做的基本上是foldLeft所做的事情,我只是交换了calcRange中的参数,它可以直接传递给foldLeft