编写Scala程序,以便在它之前找到偶数和数字

时间:2018-02-18 09:18:54

标签: scala apache-spark rdd

我编写了下面的代码,用于在RDD对象中查找偶数和它之前的数字。在这里我首先将它转换为List并尝试使用我自己的函数来找到它们之前的偶数和数字。以下是我的代码。在这里我写了一个空列表,我试图逐个追加数字。

 object EvenandOdd
 {
  def mydef(nums:Iterator[Int]):Iterator[Int]=
  {
    val mylist=nums.toList
    val len= mylist.size
    var elist=List()
    var i:Int=0
    var flag=0
    while(flag!=1)
    {
      if(mylist(i)%2==0)
      {
        elist.++=List(mylist(i))
        elist.++=List(mylist(i-1))
      }
      if(i==len-1)
      {
        flag=1
      }
      i=i+1
    }
  }
  def main(args:Array[String])
  {
    val myrdd=sc.parallelize(List(1,2,3,4,5,6,7,8,9,10),2)
    val myx=myrdd.mapPartitions(mydef)
    myx.collect
  }
 }

我无法在Scala shell和Eclipse中执行此命令,也无法找出错误,因为我只是Scala的初学者。

以下是我在Scala Shell中遇到的错误。

<console>:35: error: value ++= is not a member of List[Nothing]
               elist.++=List(mylist(i))
                     ^
<console>:36: error: value ++= is not a member of List[Nothing]
               elist.++=List(mylist(i-1))
                     ^
<console>:31: error: type mismatch;
 found   : Unit
 required: Iterator[Int]
           while(flag!=1)
           ^

4 个答案:

答案 0 :(得分:2)

您的代码看起来过于复杂且无法正常运行。此外,它引入了内存的潜在问题:您将Iterator作为参数并返回Iterator作为输出。因此,知道Iterator本身可能是懒惰的并且具有大量数据,在list方法中实现它可能会导致OOM。所以你的任务是从初始迭代器获取尽可能多的数据,因为它足以回答两个新迭代器的方法:hasNextnext

例如(基于您的实现,在偶数序列的情况下输出重复项)可能是:

  def mydef(nums:Iterator[Int]): Iterator[Int] = {
    var before: Option[Int] = None

    val helperIterator = new Iterator[(Option[Int], Int)] {
      override def hasNext: Boolean = nums.hasNext

      override def next(): (Option[Int], Int) = {
        val result = (before, nums.next())
        before = Some(result._2)
        result
      }
    }
    helperIterator.withFilter(_._2 % 2 == 0).flatMap{
      case (None, next) => Iterator(next)
      case (Some(prev), next) => Iterator(prev, next)
    }
  }

这里有两个迭代器。一个帮助器,它只是准备数据,为每个下一个提供前一个元素。接下来 - 基于辅助器,仅对序列元素(第二对)进行过滤,并在需要时输出(或者只有一个,如果序列中的第一个元素是偶数)

初始代码

除了回答@ pedrorijo91之外,在初始代码中你没有返回任何内容(假设你想将elist转换为Iterator

答案 1 :(得分:2)

如果使用功能编码样式而不是迭代编码样式,将会更容易。在功能风格上,基本操作很简单。

给定一个数字列表,以下代码将找到所有偶数和它们之前的值:

nums.sliding(2,1).filter(_(1) % 2 == 0)

滑动操作会创建一个列表,其中包含原始列表中所有可能的相邻值对 过滤操作仅采用第二个值为偶数的对 结果是Iterator [List [Int]],其中每个List [Int]有两个元素。您应该能够在RDD框架中使用它。

答案 2 :(得分:1)

它标记为开发人员API的一部分,因此不能保证它会继续存在,但RDDFunctions对象实际上为RDD定义了sliding。您必须确保它按您想要的顺序查看元素。

但这就像

rdd.sliding(2).filter(x => x(1) % 2 == 0) # pairs of (preceding number, even number)

答案 3 :(得分:0)

前两个错误:

列表中没有++=运算符。您必须执行list = list ++ element