在 Traversable 的 foreach 方法中获取当前元素的索引? [英] Get index of current element in a foreach method of Traversable?

查看:32
本文介绍了在 Traversable 的 foreach 方法中获取当前元素的索引?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个数组:

val ar1 = Array[String]("1", "2", "3")val ar2 = Array[String]("1", "2", "3", "4")

现在对于 ar1 的每个元素,我想先将该元素与 ar2 的相应元素连接起来,然后打印结果.一种方法是:

List.range(0, ar1.size).foreach(i => println(ar1(i)+ar2(i)))

如果有一个 foreach 变体可以让我直接使用 ar1 的索引而不是首先构造整数列表,那就更好了.>

也许有更好的方法?

解决方案

一种非常方便的方法是使用元组上的 zipped 方法.放入两个集合,取出函数的两个参数!

(ar1,ar2).zipped.foreach((x,y) => println(x+y))

这既方便又快速,因为您不需要构建一个元组来存储每一对(就像使用 (ar1 zip ar2) 那样),然后您必须采用再次分开.当两个集合中较短的一个用完时,两种形式的 zip 都会停止.

如果您有更复杂的事情(例如,您需要对索引进行数学运算),规范的解决方案是压缩索引:

ar1.zipWithIndex.foreach{ case(x,i) =>println(x+ar2(i)) }

您使用的方法更快更紧凑,如下所示,可能有用:

ar1.indices.foreach(i => println(ar1(i)+ar2(i)))

尽管这仅在第一个集合不长于第二个时才有效.您还可以明确指定范围:

(0 until (ar1.size min ar2.size)).foreach(i => println(ar1(i)+ar2(i)))

来解决这个问题.(您可以理解为什么首选 zipzipped,除非您所做的工作太复杂而无法轻松完成.)

如果它不是并行集合(通常不是,除非你调用 .par),虽然不推荐,但也可以使用可变变量进行跟踪:

{ var i=-1;ar1.foreach{x =>我 += 1;println(x+ar2(i)) } }

有必要这样做的情况非常有限(例如,如果您可能想跳过或回溯某些其他集合);如果您可以避免这样做,您通常会得到更容易推理的代码.

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:

List.range(0, ar1.size).foreach(i => println(ar1(i)+ar2(i)))

It would have been nicer if there was a foreach variant that would allow me to work directly with the indices of ar1 instead of first constructing the integer list.

Perhaps there is a better way?

解决方案

One very convenient way to do this is with the zipped method on tuples. Put two collections in, get out two arguments to a function!

(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.

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 zip and zipped are preferred unless what you're doing is too complicated for this to work easily.)

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:

{ 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.

这篇关于在 Traversable 的 foreach 方法中获取当前元素的索引?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆