Kotlin中的Swap函数

Kotlin中的Swap函数,kotlin,Kotlin,除了中描述的java方式外,还有其他更好的方式在kotlin中编写通用交换函数吗 有没有kotlin语言功能可以使通用交换函数更加简洁和直观?kotlin中根本不需要交换函数。您可以使用现有功能,例如: var a = 1 var b = 2 a = b.also { b = a } println(a) // print 2 println(b) // print 1 编辑:谢谢你的评论 我相信交换两个变量的代码足够简单——不必进一步简化它 IMHO最优雅的实施形式是: var a =

除了中描述的java方式外,还有其他更好的方式在kotlin中编写通用交换函数吗


有没有kotlin语言功能可以使通用交换函数更加简洁和直观?

kotlin中根本不需要交换函数。您可以使用现有功能,例如:

var a = 1
var b = 2

a = b.also { b = a }

println(a) // print 2
println(b) // print 1
编辑:谢谢你的评论

我相信交换两个变量的代码足够简单——不必进一步简化它

IMHO最优雅的实施形式是:

var a = 1
var b = 2

run { val temp = a; a = b; b = temp }

println(a) // print 2
println(b) // print 1
好处:

  • 目的是明确的。没有人会误解这一点
  • temp
    将不在范围内

    • 如果您想编写一些非常可怕的代码,您可以使用如下函数:

      inline operator fun <T> T.invoke(dummy: () -> Unit): T {
          dummy()
          return this
      }
      


      请注意,我不建议这样做。只显示它是可能的。

      Kotlin鼓励在可能的情况下使用不可变数据(例如使用
      val
      而不是
      var
      )。这大大减少了对细微错误的更改,因为如果值不变,就可以更合理地解释代码

      交换两个值在很大程度上与不可变数据相反:我是指交换之前还是之后
      a
      的值

      考虑以以下不变的方式重写代码:

      val a = 1
      val b = 2
      
      val (a2, b2) = b to a
      
      这是通过使用内置的
      to
      扩展功能来实现的,该功能创建了一对

      ,这是一个很好的用法:


      为了使用Kotlin
      List
      ,您可以创建这种扩展。它返回该列表的一个副本,其中索引a和b处的元素已交换

      fun <T> List<T>.swap(a: Int, b: Int): List<T> = this
          .toMutableList()
          .also {
              it[a] = this[b]
              it[b] = this[a]
          }
      
      fun List.swap(a:Int,b:Int):List=this
      .toMutableList()
      .还有{
      it[a]=这个[b]
      it[b]=这个[a]
      }
      
      非常简单、快速、优雅的解决方案:

      var a = 1
      var b = 2
      val (b0, a0) = a swap b
      a = a0
      b = b0
      
      infix fun <A> A.swap(second: A): Pair<A, A> = second to this
      
      var a=1
      var b=2
      val(b0,a0)=a交换b
      a=a0
      b=b0
      中缀乐趣A.swap(秒:A):Pair=仅次于此
      
      首选a=b。应用{b=a}来交换元素。 如果我们想在lambda内部的变量上执行一些操作,那么选择
      a=b.{someFun(it)}

      如果使用数组,可以使用以下命令:

      fun <T> Array<T>.swap(i: Int, j: Int) {
          with(this[i]) {
              this@swap[i] = this@swap[j]
              this@swap[j] = this
          }
      }
      
      fun Array.swap(i:Int,j:Int){
      (这个[我]){
      this@swap[i] =this@swap[j]
      this@swap[j] =这个
      }
      }
      
      如果我试图过多地思考它的实际工作原理(尽管实际上并不复杂),这会让我头疼。当你读到它的时候,它是有意义的!还有一个简单的解释。此语法是
      a=b的简写形式。另外({b=a})
      。我们还看到
      方法在
      b
      上被调用,参数为lambda
      {b=a}
      只需调用其参数,然后返回
      this
      。因此首先执行lambda
      {b=a}
      ,然后
      a
      被分配
      的结果也()
      ,这就是它的“this”,这是初始的
      b
      。太棒了!它甚至适用于数组元素:
      a[i]=a[j]。还有{a[j]=a[i]}
      @Anton3您的解释是我见过的最好的解释,但我仍然不清楚。你说lambda先被执行。这意味着b被分配了a的值,因此b被覆盖。这里有一些隐式缓冲。我反编译了a=b的字节码,也就是{b=a},在Java中得到了以下结果,这是传统的交换算法:inta=1;int b=2;字节var4=b;b=a;a=var4;那么从概念上讲,b的缓冲在何时何地发生?堆栈Closure?@Phil在Kotlin或Java中,每当参数传递给函数、返回或在闭包中捕获时,都会创建一个副本(对于对象类型,我们会复制一个对GC托管对象的引用)。然而,Kotlin用
      var
      捕获在该系统中打了一个小洞,从概念上讲,捕获是通过将值放在包装器对象中实现的,只要我们有一个对包装器对象的引用,它就允许我们改变内部值(变量名)。这实际上就是他所说的通用Java方式。所以你的答案实际上是“不,没有更好的办法”。我想我倾向于同意。更简洁地说:是的。更直观:。。。也许如果我忘记了我在编程方面学到的一切。:)绝对不是更直观。这是坏代码。我只是在玩。看起来非常可怕!:)函数应该是
      inline
      @Micha人们不再喜欢数组了?
      var a = 1
      var b = 2
      val (b0, a0) = a swap b
      a = a0
      b = b0
      
      infix fun <A> A.swap(second: A): Pair<A, A> = second to this
      
      fun <T> Array<T>.swap(i: Int, j: Int) {
          with(this[i]) {
              this@swap[i] = this@swap[j]
              this@swap[j] = this
          }
      }