我试图想出一个优雅的"迭代两个列表(值对)的解决方案,并对结果值执行一些测试。
有什么想法吗?这是我目前所拥有的,但我得到的是"值过滤器不是(List [Int],List [Int])的成员,"令我感到惊讶的是我认为这会起作用。而且,我觉得在Scala中必须有更清晰的表达方式。
val accounts = random(count = 100, minimum = 1, maximum = GPDataTypes.integer._2)
val ids = random(count = 100, minimum = 1, maximum = GPDataTypes.integer._2)
for ((id, accountId) <- (ids, accounts)) {
val g = new GPGlimple(Some(id), Some(timestamp), accountId, false, false, 2)
println(g)
g.accountId mustEqual accountId
g.id mustEqual id
g.created.get must beLessThan(System.currentTimeMillis)
g.layers must beNone
g.version must be equalTo 2
}
答案 0 :(得分:2)
最简单的解决方案是zip
:
(ids zip accounts)
zip
的文档说:
通过成对组合相应的元素,返回从此列表和另一个可迭代集合形成的列表。
换句话说,zip
将返回元组列表。
zipped
方法也适用于此处:
(ids, accounts).zipped
您可以找到2元组here
的zipped
来源。请注意,这可以通过(T, U)
的丰富来实现,其中T
可隐式查看为TraversableLike
,而U
可隐式查看为IterableLike
。该方法返回ZippedTraversable2
,这是一个封装此类压缩返回的最小接口,通过禁止创建中间集合,可以更有效地处理大型序列。这些通常更具性能,因为它们在内部使用iterators
,如源中所示。
请注意,此处的返回值不同,可能会影响下游行为。一个重要的区别是ZippedTraversable2
上的正常组合方法与元组Traversable
上的方法略有不同。 ZippedTraversable2
上的方法通常期望2个参数的函数,而Traversable
个元组上的方法将期望具有单个参数的函数是元组。例如,您可以在REPL中检查foreach
方法:
val s1 = List(1, 2, 3)
val s2 = List('a', 'b', 'c')
(s1 -> s2).zipped.foreach _
// ((Int, Char) => Any) => Unit = <function1>
(s1 zip s2).foreach _
// (((Int, Char)) => Any) => Unit = <function1>
//Notice the extra parens here, signifying a method with a tuple argument
这种差异意味着您在使用zip
和zipped
时有时必须使用不同的语法:
(s1 zip s2).map { x => x._1 + x._2 }
(s1, s2).zipped.map { x => x._1 + x._2 } //This won't work! The method shouldn't expect a tuple argument
//conversely
(s1, s2).zipped.map { (x, y) => x + y }
(s1 zip s2).map { (x, y) => x + y } //This won't work! The method shouldn't expect 2 arguments
//Added note: methods with 2 arguments can often use the more concise underscore notation:
(s1, s2).zipped.map { _ + _ }
请注意,如果您使用case
表示法,则可以采用以下方式覆盖:
//case works for both syntaxes
(s1, s2).zipped.map { case (x, y) => x + y } \
(s1 zip s2).map { case (x, y) => x + y }
这是有效的,因为编译器理解带有两个参数或单个元组参数的方法的这种表示法,如section 8.5 of the spec中所述:
val f: (Int, Int) => Int = { case (a, b) => a + b }
val g: ((Int, Int)) => Int = { case (a, b) => a + b }
答案 1 :(得分:1)
使用zip:
for ((id, accountId) <- ids.zip(accounts)) {
// ...
}