加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在scala中以5的幂递增for循环(循环变量)

发布时间:2020-12-16 08:53:15 所属栏目:安全 来源:网络整理
导读:我曾在 Javaranch问过这个问题,但在那里得不到答复.所以在这里发布它: 我有这个特殊要求,其中循环变量的增量是通过在每次迭代后将它乘以5来完成的.在Java中,我们可以这样实现它: for(int i=1;i100;i=i*5){} 在scala我尝试以下代码 – var j=1for(i-1.to(10
我曾在 Javaranch问过这个问题,但在那里得不到答复.所以在这里发布它:

我有这个特殊要求,其中循环变量的增量是通过在每次迭代后将它乘以5来完成的.在Java中,我们可以这样实现它:

for(int i=1;i<100;i=i*5){}

在scala我尝试以下代码 –

var j=1
for(i<-1.to(100).by(scala.math.pow(5,j).toInt))
{
  println(i+" "+j)
  j=j+1
}

但它的打印输出如下:
1 1
6 2
11 3
16 4
21 5
26 6
31 7
36 8
….
….

它总是递增5.那么我如何实际将增量乘以5而不是添加它.

解决方法

我们先解释一下这个问题.这段代码:

var j=1
for(i<-1.to(100).by(scala.math.pow(5,j).toInt))
{
  println(i+" "+j)
  j=j+1
}

相当于:

var j = 1
val range: Range = Predef.intWrapper(1).to(100)
val increment: Int = scala.math.pow(5,j).toInt
val byRange: Range = range.by(increment)
byRange.foreach {
  println(i+" "+j)
  j=j+1
}

因此,当你变异j时,已经计算了increment和byRange.而Range是一个不可变的对象 – 你无法改变它.即使你在做foreach时产生了新的范围,做foreach的对象仍然是相同的.

现在,到解决方案.简而言之,Range不足以满足您的需求.你想要几何级数,而不是算术级数.对我来说(似乎其他所有人都在回答),自然的解决方案是使用使用iterate创建的Stream或Iterator,它根据前一个值计算下一个值.

for(i <- Iterator.iterate(1)(_ * 5) takeWhile (_ < 100)) {
  println(i)
}

编辑:关于Stream vs Iterator

Stream和Iterator是非常不同的数据结构,它们共享非严格的属性.这个属性使迭代甚至存在,因为这个方法创建了一个无限集合1,takeWhile将从中创建一个有限的new2集合.我们来看看:

val s1 = Stream.iterate(1)(_ * 5) // s1 is infinite
val s2 = s1.takeWhile(_ < 100)    // s2 is finite
val i1 = Iterator.iterate(1)(_ * 5) // i1 is infinite
val i2 = i1.takeWhile(_ < 100)      // i2 is finite

这些无限集合是可能的,因为集合不是预先计算的.在列表中,列表中的所有元素实际上都是在创建列表时存储在某处.然而,在上面的例子中,只预先知道每个集合的第一个元素.只有在需要时才会计算所有其他数据.

正如我所提到的,这些在其他方面是非常不同的集合. Stream是一种不可变的数据结构.例如,您可以根据需要多次打印s2的内容,并且每次都会显示相同的输出.另一方面,Iterator是一个可变数据结构.一旦你使用了一个值,那个价值就永远消失了.打印i2的内容两次,第二次打印为空:

scala> s2 foreach println
1
5
25

scala> s2 foreach println
1
5
25

scala> i2 foreach println
1
5
25

scala> i2 foreach println

scala>

另一方面,Stream是一个懒惰的集合.一旦计算了一个值,它就会保持计算,而不是每次都被丢弃或重新计算.请参阅下面的行为中的一个示例:

scala>     val s2 = s1.takeWhile(_ < 100)    // s2 is finite
s2: scala.collection.immutable.Stream[Int] = Stream(1,?)

scala> println(s2)
Stream(1,?)

scala> s2 foreach println
1
5
25

scala> println(s2)
Stream(1,5,25)

因此,如果不小心,Stream实际上可以填满内存,而Iterator占用恒定的空间.另一方面,Iterator会因为它的副作用而感到惊讶.

(1)事实上,Iterator根本不是一个集合,尽管它分享了很多集合提供的方法.另一方面,从您给出的问题描述中,您并不真正感兴趣的是拥有一组数字,只是在迭代它们.

(2)实际上,虽然takeWhile会在Scala 2.8.0上创建一个新的Iterator,但是这个新的迭代器仍然会链接到旧的迭代器,而其中一个的变化会对另一个产生副作用.这需要讨论,它们最终可能在未来真正独立.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读