【问题标题】:How refactor incrementing in scala?如何在scala中重构增量?
【发布时间】:2014-11-06 07:32:59
【问题描述】:

我有这样的代码:

var index = 0
var array: Array[String] = //initialized

functionOne(array(index))
index = index + 1
functionTwo(array(index))
index = index + 1

这个想法很明确 - 每次从数组中获取元素时,我都需要增加索引。使用 java 可以简单地编写 index++ 而不是到处复制 index = index+ 1。有没有用 scala 重构上面代码的模式/api?

【问题讨论】:

  • 你可以使用index += 1

标签: java scala increment


【解决方案1】:

如果用例是为数组的每个元素调用不同的函数,那么更简洁的解决方案是

var array: Array[String] = ??? // intialized
// as many functions as needed
val functions = Array(functionOne, functionTwo, functionThree);  

(array zip functions) foreach { case (el, f) => f(el) }

这是一个更一般的想法的示例,如果您没有对索引值做任何事情,只是使用它来访问集合,那么可能有一种不需要索引的方法全部。

【讨论】:

    【解决方案2】:

    Scala 没有增量运算符。在适当的地方你可以使用index+=1。请参考Why no i++ in scala?

    【讨论】:

    • 但是还是有两行代码,而不是 Java 中的一行。
    • @rtruszk,不会有相同数量的行。在 java 中,2x index++。在 Scala 中,2x index+=1
    • @Paul 否。在 Java 中是一行:functionOne(array[index++]),在 Scala 中是两行:functionOne(array(index)) 和 index+=1
    • 是的,您可以将其写在一行中,但 OP 没有。所以我不认为两者是等价的。无论如何,根本不需要搞乱索引。看我的回答
    【解决方案3】:

    你是在命令式而不是功能上思考。如果你想在 Scala 中对数组中的每个元素应用一个函数,那么惯用的做法是利用 map 函数,这样你就有了类似的东西:

    val elements = Array(1,2,3,4,5)
    val results = elements map { x => x+4}
    

    如果您需要在函数调用中使用每个元素的索引,则使用带有索引的 zip 将数组转换为对数组(或序列),如下所示:

    scala> elements.zipWithIndex
    res0: Array[(Int, Int)] = Array((1,0), (2,1), (3,2), (4,3), (5,4), (6,5))
    

    然后你可以再次应用一个映射,这次应用一个函数,它接受一对而不是单个元素:

    scala> elements.zipWithIndex map { case (x,y) => (x, y*5) }
    res2: Array[(Int, Int)] = Array((1,0), (2,5), (3,10), (4,15), (5,20), (6,25))
    

     scala> elements.zipWithIndex map { case (x, y) => x*y }
     res3: Array[Int] = Array(0, 2, 6, 12, 20, 30)
    

    如果你想为每个索引应用不同的函数,那么只需在 map 闭包中提供不同的定义:

    scala> elements.zipWithIndex map { 
       case (0, y) => y + 45
     | case (1, y) => y + 5
     | case (_, y) => y
     | }
    

    【讨论】:

    • 数组元素不同功能的应用问题。例如。 functionOnefunctionTwo 是不同的函数调用。
    • 在这种情况下,您只需在 map 闭包中使用不同的函数定义...根据传入的索引而改变...
    • 地图中的案例非常难看。如果 OP 想首先调用一个函数,第二个调用不同的函数,以此类推,那么更好的是 (array.toList zip List( functionOne, functionTwo,[etc.])).foreach(case (el, f) => f(el))?
    • 是的 - 好点保罗。这真的更干净,更具可读性。
    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 2020-04-26
    • 2016-01-14
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 2010-09-18
    • 2021-01-31
    相关资源
    最近更新 更多