ohr*_*uus 3 scala iterable-unpacking
Scala能够在执行各种操作时将元组解压缩为多个局部变量,例如,如果我有一些数据
val infos = Array(("Matt", "Awesome"), ("Matt's Brother", "Just OK"))
Run Code Online (Sandbox Code Playgroud)
而不是做一些丑陋的事情
infos.map{ person_info => person_info._1 + " is " + person_info._2 }
Run Code Online (Sandbox Code Playgroud)
我可以选择更优雅
infos.map{ case (person, status) => person + " is " + status }
Run Code Online (Sandbox Code Playgroud)
我经常想知道的一件事是如何将元组直接解压缩到比如在类构造函数中使用的参数.我想象的是这样的:
case class PersonInfo(person: String, status: String)
infos.map{ case (p: PersonInfo) => p.person + " is " + p.status }
Run Code Online (Sandbox Code Playgroud)
如果PersonInfo有方法,甚至更好:
infos.map{ case (p: PersonInfo) => p.verboseStatus() }
Run Code Online (Sandbox Code Playgroud)
但当然这不起作用.如果已经有人问过这个道歉 - 我还没有找到直接答案 - 有没有办法做到这一点?
我相信你至少可以在Scala 2.11.x中找到这些方法,如果你还没有听说过,你应该查看新手指南Scala第1部分:提取器.
整个16部分系列很棒,但第1部分涉及案例类,模式匹配和提取器,这是我认为你所追求的.
此外,我java.lang.String也在IntelliJ中得到了这个投诉,默认是因为我不完全清楚的原因,我能够通过明确地设置典型的"后缀样式"类型来解决它_: String.必须有一些方法来解决这个问题.
object Demo {
case class Person(name: String, status: String) {
def verboseStatus() = s"The status of $name is $status"
}
val peeps = Array(("Matt", "Alive"), ("Soraya", "Dead"))
peeps.map {
case p @ (_ :String, _ :String) => Person.tupled(p).verboseStatus()
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
在看到其他一些答案后,我很好奇他们之间是否有任何性能差异.所以我设置了,我认为使用1,000,000个随机字符串元组的数组进行合理的测试,每个实现运行100次:
import scala.util.Random
object Demo extends App {
//Utility Code
def randomTuple(): (String, String) = {
val random = new Random
(random.nextString(5), random.nextString(5))
}
def timer[R](code: => R)(implicit runs: Int): Unit = {
var total = 0L
(1 to runs).foreach { i =>
val t0 = System.currentTimeMillis()
code
val t1 = System.currentTimeMillis()
total += (t1 - t0)
}
println(s"Time to perform code block ${total / runs}ms\n")
}
//Setup
case class Person(name: String, status: String) {
def verboseStatus() = s"$name is $status"
}
object PersonInfoU {
def unapply(x: (String, String)) = Some(Person(x._1, x._2))
}
val infos = Array.fill[(String, String)](1000000)(randomTuple)
//Timer
implicit val runs: Int = 100
println("Using two map operations")
timer {
infos.map(Person.tupled).map(_.verboseStatus)
}
println("Pattern matching and calling tupled")
timer {
infos.map {
case p @ (_: String, _: String) => Person.tupled(p).verboseStatus()
}
}
println("Another pattern matching without tupled")
timer {
infos.map {
case (name, status) => Person(name, status).verboseStatus()
}
}
println("Using unapply in a companion object that takes a tuple parameter")
timer {
infos.map { case PersonInfoU(p) => p.name + " is " + p.status }
}
}
/*Results
Using two map operations
Time to perform code block 208ms
Pattern matching and calling tupled
Time to perform code block 130ms
Another pattern matching without tupled
Time to perform code block 130ms
WINNER
Using unapply in a companion object that takes a tuple parameter
Time to perform code block 69ms
*/
Run Code Online (Sandbox Code Playgroud)
假设我的测试是合理的,似乎在同伴上下的对象不应用在2倍〜比模式匹配更快,模式匹配另一〜1.5倍比两张地图快.每个实现可能都有其用例/限制.
我很感激,如果有人在我的测试策略中看到任何明显愚蠢的东西让我知道它(并对那个var感到抱歉).谢谢!
| 归档时间: |
|
| 查看次数: |
692 次 |
| 最近记录: |