迭代 Scala 元组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18668642/
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
Iteration over Scala tuples
提问by deepkimo
In scala, we can get an iterator over a tuple as follows
在scala中,我们可以得到一个元组上的迭代器,如下所示
val t = (1, 2)
val it = t.productIterator
and even
乃至
it.foreach( x => println(x.isInstanceOf[Int]) )
returns true, we cannot do simple operations on the iterator values without using asInstanceOf[Int], since
返回 true,我们不能在不使用 asInstanceOf[Int] 的情况下对迭代器值进行简单操作,因为
it.foreach( x => println(x+1) )
returns an error: type mismatch; found : Int(1) required: String
返回错误:类型不匹配;发现:Int(1) 需要:字符串
I understand the issue with Integer vs. Int, but still the validity of isInstanceOf[Int] is somewhat confusing.
我理解 Integer 与 Int 的问题,但 isInstanceOf[Int] 的有效性仍然有些混乱。
What is the best way to do these operations over tuples? Notice that the tuple can have a mix of types like integers with doubles, so converting to a list might not always work.
对元组进行这些操作的最佳方法是什么?请注意,元组可以混合使用整数和双精度类型,因此转换为列表可能并不总是有效。
回答by user2246674
A tuple does not have to be homogenous and the compiler didn't try to apply magic type unification across the elements1. Take (1, "hello")as an example of such a a heterogenous tuple (Tuple2[Int,String]).
元组不必是同质的,并且编译器没有尝试跨元素应用魔法类型统一1。以(1, "hello")这种异质元组( Tuple2[Int,String])为例。
This means that xis typed as Any(not Int!). Try it.foreach( (x: Int) => println(x) ), with the original tuple, to get a better error message indicating that the iterator is notunified over the types of the tuple elements (it is an Iterators[Any]). The error reported should be similar to:
这意味着x输入为Any(不是Int!)。尝试it.foreach( (x: Int) => println(x) )使用原始元组获得更好的错误消息,表明迭代器在元组元素的类型上没有统一(它是Iterators[Any])。报告的错误应该类似于:
error: type mismatch;
found : (Int) => Unit
required: (Any) => ?
(1, 2).productIterator.foreach( (x: Int) => println(x) )
In this particular case isInstanceOf[Int]can be used to refine the type - from the Anythat the type-system gave us - because weknow, from manual code inspection, that it will "be safe" with the given tuple.
在这种特殊情况下,isInstanceOf[Int]可用于细化类型 - 从Any类型系统给我们的类型 - 因为我们知道,从手动代码检查中,它对于给定的元组是“安全的”。
Here is another look at the iterators/types involved:
这是所涉及的迭代器/类型的另一种看法:
(1, 2) // -> Tuple2[Int,Int]
.productIterator // -> Iterator[Any]
.map(_.asInstanceOf[Int]) // -> Iterator[Int]
.foreach(x => println(x+1))
While I would recommend treating tuples as finite sets of homogenous elementsand not a sequence, the same rules can be used as when dealing with any Iterator[Any]such as using pattern matching (e.g. match) that discriminates by the actual object type. (In this case the code is using an implicit PartialFunction.)
虽然我建议将元组视为同质元素的有限集而不是序列,但可以使用与处理任何规则相同的规则,Iterator[Any]例如使用模式匹配(例如match)区分实际对象类型。(在这种情况下,代码使用的是隐式 PartialFunction。)
(1, "hello").productIterator
.foreach {
case s: String => println("string: " + s)
case i: Int => println("int: " + i)
}
1While it might be possible to make the compiler unify the types in this scenario, it sounds like a special case that requires extra work for minimal gain. Normally sequences like lists - not tuples - are used for homogenous elements and the compiler/type-system correctly gives us a good refinement for something like List(1,2)(which is typed as List[Int]as expected).
1虽然在这种情况下可以让编译器统一类型,但这听起来像是一种特殊情况,需要额外的工作才能获得最小的收益。通常像列表这样的序列 - 而不是元组 - 用于同质元素,编译器/类型系统正确地为我们提供了一个很好的改进List(1,2)(List[Int]按预期输入)。

