在 Scala 中使用循环时使事物不可变
Making things immutable while working with loops in Scala
我已经用 Scala 编写了几行代码,但不知道如何使用不可变变量 (val) 来实现同样的功能。任何帮助将不胜感激。
class Test {
def process(input: Iterable[(Double, Int)]): (Double, Int) = {
var maxPrice: Double = 0.0
var maxVolume: Int = 0
for ((price, volume) <- input) {
if (price > maxPrice) {
maxPrice = price
}
if (volume > maxVolume) {
maxVolume = volume
}
}
(maxPrice, maxVolume)
}
}
任何人都可以帮助我将所有 var 转换为 val 并使其更具功能性吗?
提前致谢! :)
使用.foldLeft
:
def process(input: Iterable[(Double, Int)]): (Double, Int) =
input.foldLeft(0.0 -> 0) { case ((maxPrice, maxVolume), (price, volume)) =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
newPrice -> newVolume
}
为了比较这里是尾递归解决方案
def process(input: Iterable[(Double, Int)]): (Double, Int) = {
@tailrec def loop(remaining: Iterable[(Double, Int)], maxPrice: Double, maxVolume: Int): (Double, Int) = {
remaining match {
case Nil => maxPrice -> maxVolume
case (price, volume) :: tail =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
loop(tail, newPrice, newVolume)
}
}
loop(input, 0, 0)
}
和相应的jmh基准
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So61366933 {
def mario(input: Iterable[(Double, Int)]): (Double, Int) = {
@tailrec def loop(remaining: Iterable[(Double, Int)], maxPrice: Double, maxVolume: Int): (Double, Int) = {
remaining match {
case Nil => maxPrice -> maxVolume
case (price, volume) :: tail =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
loop(tail, newPrice, newVolume)
}
}
loop(input, 0, 0)
}
def mateusz(input: Iterable[(Double, Int)]): (Double, Int) =
input.foldLeft(0.0 -> 0) { case ((maxPrice, maxVolume), (price, volume)) =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
newPrice -> newVolume
}
import scala.util.Random._
def arbTuple: (Double, Int) = nextDouble() -> nextInt()
val input = List.fill(1000)(arbTuple)
@Benchmark def foldLeft = mateusz(input)
@Benchmark def tailRec = mario(input)
}
哪里
sbt "jmh:run -i 5 -wi 5 -f 2 -t 1 bench.So61366933"
产出
[info] Benchmark Mode Cnt Score Error Units
[info] So61366933.foldLeft thrpt 10 80999.752 ± 2118.095 ops/s
[info] So61366933.tailRec thrpt 10 259875.842 ± 7718.674 ops/s
我已经用 Scala 编写了几行代码,但不知道如何使用不可变变量 (val) 来实现同样的功能。任何帮助将不胜感激。
class Test {
def process(input: Iterable[(Double, Int)]): (Double, Int) = {
var maxPrice: Double = 0.0
var maxVolume: Int = 0
for ((price, volume) <- input) {
if (price > maxPrice) {
maxPrice = price
}
if (volume > maxVolume) {
maxVolume = volume
}
}
(maxPrice, maxVolume)
}
}
任何人都可以帮助我将所有 var 转换为 val 并使其更具功能性吗? 提前致谢! :)
使用.foldLeft
:
def process(input: Iterable[(Double, Int)]): (Double, Int) =
input.foldLeft(0.0 -> 0) { case ((maxPrice, maxVolume), (price, volume)) =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
newPrice -> newVolume
}
为了比较这里是尾递归解决方案
def process(input: Iterable[(Double, Int)]): (Double, Int) = {
@tailrec def loop(remaining: Iterable[(Double, Int)], maxPrice: Double, maxVolume: Int): (Double, Int) = {
remaining match {
case Nil => maxPrice -> maxVolume
case (price, volume) :: tail =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
loop(tail, newPrice, newVolume)
}
}
loop(input, 0, 0)
}
和相应的jmh基准
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So61366933 {
def mario(input: Iterable[(Double, Int)]): (Double, Int) = {
@tailrec def loop(remaining: Iterable[(Double, Int)], maxPrice: Double, maxVolume: Int): (Double, Int) = {
remaining match {
case Nil => maxPrice -> maxVolume
case (price, volume) :: tail =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
loop(tail, newPrice, newVolume)
}
}
loop(input, 0, 0)
}
def mateusz(input: Iterable[(Double, Int)]): (Double, Int) =
input.foldLeft(0.0 -> 0) { case ((maxPrice, maxVolume), (price, volume)) =>
val newPrice = if (maxPrice < price) price else maxPrice
val newVolume = if (maxVolume < volume) volume else maxVolume
newPrice -> newVolume
}
import scala.util.Random._
def arbTuple: (Double, Int) = nextDouble() -> nextInt()
val input = List.fill(1000)(arbTuple)
@Benchmark def foldLeft = mateusz(input)
@Benchmark def tailRec = mario(input)
}
哪里
sbt "jmh:run -i 5 -wi 5 -f 2 -t 1 bench.So61366933"
产出
[info] Benchmark Mode Cnt Score Error Units
[info] So61366933.foldLeft thrpt 10 80999.752 ± 2118.095 ops/s
[info] So61366933.tailRec thrpt 10 259875.842 ± 7718.674 ops/s