将 scala 中的 for 循环(循环变量)增加 5 次方
我曾在 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 而不是相加呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我们先来解释一下问题。此代码:
等价于:
因此,当您开始改变
j
时,increment
和byRange
已经被计算出来。Range
是一个不可变对象——您无法更改它。即使您在执行foreach
时生成了新范围,执行foreach
的对象仍然是相同的。现在,解决方案。简而言之,
Range
不足以满足您的需求。你想要的是几何级数,而不是算术级数。对我来说(似乎几乎所有其他人都在回答),自然的解决方案是使用使用iterate
创建的Stream
或Iterator
,它根据前一个值计算下一个值。编辑:关于 Stream 与 Iterator
Stream
和Iterator
是非常不同的数据结构,它们共享非严格的属性嗯>。此属性使iterate
甚至能够存在,因为此方法正在创建一个无限集合1,takeWhile
将从中创建一个 new2 集合是有限的。让我们看看这里:这些无限集合是可能的,因为集合不是预先计算的。在
List
上,列表内的所有元素实际上在创建列表时都存储在某处。然而,在上面的示例中,只有每个集合的第一个元素是提前已知的。所有其他内容仅在需要时才会计算。不过,正如我所提到的,这些集合在其他方面是非常不同的。
Stream
是一种不可变
数据结构。例如,您可以根据需要多次打印s2
的内容,并且每次都会显示相同的输出。另一方面,迭代器是一种可变数据结构。一旦你使用了一个值,这个值就会永远消失。打印i2
的内容两次,第二次它将为空:另一方面,
Stream
是一个lazy
集合。一旦计算出一个值,它将保持计算状态,而不是每次都被丢弃或重新计算。请参阅下面该行为的一个示例:因此,如果不小心,
Stream
实际上会填满内存,而Iterator
则占用恒定空间。另一方面,由于它的副作用,Iterator
可能会让人感到惊讶。(1) 事实上,
Iterator
根本不是一个集合,尽管它共享集合提供的很多方法。另一方面,从您给出的问题描述来看,您对数字集合并不真正感兴趣,只是对它们进行迭代。(2) 实际上,虽然
takeWhile
在 Scala 2.8.0 上会创建一个新的Iterator
,但这个新的迭代器仍然会链接到旧的迭代器,并且其中的变化是有副作用的对对方的影响。这还有待讨论,他们将来可能最终会真正独立。Let's first explain the problem. This code:
is equivalent to this:
So, by the time you get to mutate
j
,increment
andbyRange
have already been computed. AndRange
is an immutable object -- you can't change it. Even if you produced new ranges while you did theforeach
, the object doing theforeach
would still be the same.Now, to the solution. Simply put,
Range
is not adequate for your needs. You want a geometric progression, not an arithmetic one. To me (and pretty much everyone else answering, it seems), the natural solution would be to use aStream
orIterator
created withiterate
, which computes the next value based on the previous one.EDIT: About Stream vs Iterator
Stream
andIterator
are very different data structures, that share the property of being non-strict. This property is what enablesiterate
to even exist, since this method is creating an infinite collection1, from whichtakeWhile
will create a new2 collection which is finite. Let's see here:These infinite collections are possible because the collection is not pre-computed. On a
List
, all elements inside the list are actually stored somewhere by the time the list has been created. On the above examples, however, only the first element of each collection is known in advance. All others will only be computed if and when required.As I mentioned, though, these are very different collections in other respects.
Stream
is animmutable
data structure. For instance, you can print the contents ofs2
as many times as you wish, and it will show the same output every time. On the other hand,Iterator
is a mutable data structure. Once you used a value, that value will be forever gone. Print the contents ofi2
twice, and it will be empty the second time around:Stream
, on the other hand, is alazy
collection. Once a value has been computed, it will stay computed, instead of being discarded or recomputed every time. See below one example of that behavior in action:So
Stream
can actually fill up the memory if one is not careful, whereasIterator
occupies constant space. On the other hand, one can be surprised byIterator
, because of its side effects.(1) As a matter of fact,
Iterator
is not a collection at all, even though it shares a lot of the methods provided by collections. On the other hand, from the problem description you gave, you are not really interested in having a collection of numbers, just in iterating through them.(2) Actually, though
takeWhile
will create a newIterator
on Scala 2.8.0, this new iterator will still be linked to the old one, and changes in one have side effects on the other. This is subject to discussion, and they might end up being truly independent in the future.以更实用的风格:
并使用更多语法糖:
In a more functional style:
And with more syntactic sugar:
也许一个简单的 while 循环就可以了?
或者如果您还想打印迭代次数
,看来你们喜欢功能性的,那么递归解决方案?
Maybe a simple while-loop would do?
or if you want to also print the number of iterations
it seems you guys likes functional so how about a recursive solution?
更新:感谢您发现错误...它当然应该是幂,而不是乘法:
令人烦恼的是,标准中似乎没有整数
pow
函数图书馆!试试这个:
或者如果你想就地使用它:
并与索引一起使用:
Update: Thanks for spotting the error... it should of course be power, not multiply:
Annoyingly, there doesn't seem to be an integer
pow
function in the standard library!Try this:
Or if you want to use it in-place:
and with the indices:
生成一个向量,其中 i,j 的顺序相反。
produces a Vector, with i,j in reversed order.