scala 在 Traversable 的 foreach 方法中获取当前元素的索引?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6821194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get index of current element in a foreach method of Traversable?
提问by Jus12
Suppose I have two arrays:
假设我有两个数组:
val ar1 = Array[String]("1", "2", "3")
val ar2 = Array[String]("1", "2", "3", "4")
Now for each element of ar1, I want to first concatenate that element with the corresponding element of ar2, and then print the result. One way to do would be something like:
现在对于 的每个元素ar1,我想首先将该元素与 的相应元素连接起来,ar2然后打印结果。一种方法是:
List.range(0, ar1.size).foreach(i => println(ar1(i)+ar2(i)))
It would have been nicer if there was a foreachvariant that would allow me to work directly with the indices of ar1instead of first constructing the integer list.
如果有一个foreach变体可以让我直接使用 的索引ar1而不是首先构造整数列表,那就更好了。
Perhaps there is a better way?
也许有更好的方法?
回答by Rex Kerr
One very convenient way to do this is with the zippedmethod on tuples. Put two collections in, get out two arguments to a function!
一种非常方便的方法是使用zipped元组上的方法。放入两个集合,取出函数的两个参数!
(ar1,ar2).zipped.foreach((x,y) => println(x+y))
This is both convenient to write and fast, since you don't need to build a tuple to store each pair (as you would with (ar1 zip ar2)) which you then have to take apart again. Both forms of zip stop when the shorter of the two collections is exhausted.
这既方便又快速,因为您不需要构建一个元组来存储每一对(就像使用(ar1 zip ar2)),然后您必须再次拆开它们。当两个系列中较短的一个用完时,两种形式的拉链都会停止。
If you have something more complicated (e.g. you need to do math on the index), the canonical solution is to zip in the index:
如果您有更复杂的事情(例如,您需要对索引进行数学运算),规范的解决方案是压缩索引:
ar1.zipWithIndex.foreach{ case(x,i) => println(x+ar2(i)) }
The method you are using is more rapidly and compactly done as follows, an can be useful:
您正在使用的方法更快速,更紧凑,如下所示,这可能很有用:
ar1.indices.foreach(i => println(ar1(i)+ar2(i)))
although this only works if the first collection is no longer than the second. You can also specify your ranges explcitly:
尽管这只适用于第一个集合不超过第二个集合的情况。您还可以明确指定您的范围:
(0 until (ar1.size min ar2.size)).foreach(i => println(ar1(i)+ar2(i)))
to get around this problem. (You can see why zipand zippedare preferred unless what you're doing is too complicated for this to work easily.)
解决这个问题。(您可以理解为什么zip并且zipped是首选,除非您正在做的事情太复杂而无法轻松完成。)
If it is not a parallel collection (and usually it is not unless you call .par), it's also possible, though not recommended, to keep track with a mutable variable:
如果它不是并行集合(通常不是,除非您调用.par),虽然不推荐,但也可以跟踪可变变量:
{ var i=-1; ar1.foreach{ x => i += 1; println(x+ar2(i)) } }
There are a very limited number of cases where this is necessary (e.g. if you may want to skip or backtrack on some of the other collection(s)); if you can avoid having to do this, you'll usually end up with code that's easier to reason about.
有必要这样做的情况非常有限(例如,如果您可能想跳过或回溯某些其他集合);如果你可以避免这样做,你通常会得到更容易推理的代码。
回答by missingfaktor
This is how you loop with an index in idiomatic Scala:
这是在惯用的 Scala 中使用索引循环的方式:
scala> List("A", "B", "C").zipWithIndex foreach { case(el, i) =>
| println(i + ": " + el)
| }
0: A
1: B
2: C
And here is the idiomatic Scala way to do what you are trying to achieve in your code:
这里是用惯用的 Scala 方式来完成您想要在代码中实现的目标:
scala> val arr1 = Array("1", "2", "3")
arr1: Array[java.lang.String] = Array(1, 2, 3)
scala> val arr2 = Array("1", "2", "3", "4")
arr2: Array[java.lang.String] = Array(1, 2, 3, 4)
scala> (arr1, arr2).zipped.map(_ + _) foreach println
11
22
33
回答by gizmo
I did not had the opportunity to test it, but this should do the trick:
我没有机会测试它,但这应该可以解决问题:
ar1.zip(ar2).foreach(x => println(x._1 +x._2))
回答by Tomasz Nurkiewicz
zipwill do it:
zip会做的:
ar1 zip ar2 foreach { p => println(p._1 + p._2) }
This will yield:
这将产生:
11
22
33
Note that you don't need [String]generic type, will be infered by the compiler:
请注意,您不需要[String]泛型类型,编译器会推断:
val ar1 = Array("1", "2", "3")
val ar2 = Array("1", "2", "3", "4")

