【问题标题】:Write a Scala Programs to find even numbers and a number just before it编写一个Scala程序来查找偶数和它之前的数字
【发布时间】:2018-02-18 09:18:54
【问题描述】:

我编写了下面的代码,用于在 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)
           ^

【问题讨论】:

  • 请显示您遇到的具体错误。
  • @n.m.我已添加收到的错误。
  • a) 不要使用变量。 b) 3 消息通知您,while 循环计算为一个单元。作为您方法的最后一条语句,它违反了断言,返回一个 Iterator[Int]。 c) 输入数据的期望结果是什么? d) 什么是 sc (sc.parallelize ...)?

标签: scala apache-spark rdd


【解决方案1】:

您的代码看起来太复杂且无法正常工作。此外,它还引入了内存的潜在问题:您将 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

【讨论】:

    【解决方案2】:

    如果你使用函数式编码风格而不是迭代式编码风格会更容易。在函数式风格中,基本操作很简单。

    给定一个数字列表,以下代码将找到所有偶数及其前面的值:

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

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

    【讨论】:

    • 那 (sliding) 不会对性能产生影响吗?无论如何,由于nums是一个迭代器,我认为这种“滑动操作创建一个包含所有可能对的列表”并不完全正确。
    • @ZenMaster JosephChacko 没有提到将 RDD 转换为 Iterable 的问题吗?一旦完成,性能无论如何都无关紧要。但是,具有滑动窗口的解决方案实际上可能适用于 Spark 数据集。
    • @AndreyTyukin 是的,我更关心一般情况,比如 Spark。
    【解决方案3】:

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

    但这变成了类似

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

    【讨论】:

      【解决方案4】:

      对于前 2 个错误:

      列表中没有++= 运算符。你必须这样做list = list ++ element

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      相关资源
      最近更新 更多