2011-07-25 115 views
48

假设我有两个数组:在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指数上班的第一构建整数列表,而不是。

也许有更好的办法吗?

+0

另请参见http://stackoverflow.com/questions/6833501/efficient-iteration-with-index-in-scala – Vadzim

回答

84

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

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

这是既方便编写和快速,因为你并不需要建立一个元组来存储每对(你会与(ar1 zip ar2)),这你就必须重新拆开。当两个集合中较短的一个用尽时,两种形式的拉链停止。

如果你有更复杂的东西(例如,你需要做的索引数学),规范的解决方案是在索引号邮编:

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

您正在使用的方法更快速和紧凑做如下所示,一个可以是有用的:

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

虽然这只适用于如果第一个集合不再比第二个集合。您还可以指定您的范围explecitly:

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

解决此问题。 (你可以看到为什么zipzipped是首选的,除非你所做的事情太复杂了,以至于无法轻松工作。)

如果它不是一个平行的集合(通常是不,除非你打电话.par),它也有可能,但不推荐,跟踪与可变变量:

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

有一个非常有限的情况下,这是必要的(例如,如果你想跳过或回溯一些其他收藏品);如果你可以避免这样做,你通常会得到更容易推理的代码。

+1

我没有回答这个问题,因为问题明确询问'Traversable',而'Traversable'没有'zipWithIndex' - 这很烦人。 –

+0

@WilfredSpringer - 这个问题并不问''Traversable',它只是表示想在某个时候使用'foreach'。 –

+0

不要误解我的意思。我会投票答复你的答案。我只是说这个问题是:“在* Traversable *的foreach方法中获取当前元素的索引?”所以它的出发点似乎是“穿越”;至少这就是我*如何阅读这个问题。 –

4

我并没有机会来测试它,但是这应该做的伎俩:

ar1.zip(ar2).foreach(x => println(x._1 +x._2)) 
+0

通过添加变量修复了'_'的两次使用。 –

3

zip将做到这一点:

ar1 zip ar2 foreach { p => println(p._1 + p._2) } 

这将产生:

11 
22 
33 

请注意,您不需要[String]泛型类型,将由编译器引发:

val ar1 = Array("1", "2", "3") 
val ar2 = Array("1", "2", "3", "4") 
34

你这是怎么用惯用的斯卡拉指数环:

scala> List("A", "B", "C").zipWithIndex foreach { case(el, i) => 
    | println(i + ": " + el) 
    | } 
0: A 
1: B 
2: C 

这里是地道的斯卡拉的方式做你想在你的代码来实现的:

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 
+0

这也是一个非常好的答案。 – Jus12