Swap Function in Kotlin

Viewed 32009

is there any better way to write generic swap function in kotlin other than java way described in How to write a basic swap function in Java.

Is there any kotlin language feature which can make generic swap function more concise and intuitive?

12 Answers

Very simple, fast and elegant solution:

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

prefer a=b.apply {b=a} for swapping the elements. If we want to perform some operation on the variable inside the lambda, then go for a = b.also {someFun(it)}

If you're swapping array values in place, from a code readability perspective, it was helpful for me to add an extension function swapInPlace

fun <T> Array<T>.swapInPlace(i1: Int, i2: Int){
  this[i1] = this[i2].also{ this[i2] = this[i1] }
}

fun main(){
 val numbers = arrayOf(2, 1)

 //This is easier for me to read...
 numbers.swapInPlace(0, 1)

 //Compared to this
 numbers[0] = numbers[1].also{ numbers[1] = numbers[0] }
}

I have something interesting for all:

Why just numbers. We can swap anything with a generic class and a generic function

class Mutable<T>(var value: T) {
    override fun toString() = value.toString()

    /**
    infix fun swapWith(other: Mutable<T>) {
        value = other.value.also { other.value = value }
    }
    **/
}

fun <T> swap(num1: Mutable<T>, num2: Mutable<T>) {
    num1.value = num2.value.also { num2.value = num1.value }
}

fun main() {
    val num1 = Mutable(4)
    val num2 = Mutable(6)

    println("Before Swapping:-\n\tNumber#1 is: $num1\n\tNumber#2 is: $num2\n")

    //calling way of class method is not like usual swap function
    //num1 swapWith num2

    //calling the actual swap function.
    swap(num1, num2)

    println("After Swapping:-\n\tNumber#1 is: $num1\n\tNumber#2 is: $num2\n")
}
  • class Mutable is a generic class here which can contain any type of data into it.

I overridden toString() method to directly accessing the value attribute by just calling the object.

  • fun swap is a true swap function for kotlin that gives you the call by reference's demo too.

  • operator swapWith also works as swap function, which is a part of Mutable class. I have commented that part because the calling way for the operator is not like the way we are used to with.

Output:

Before Swapping:-
    Number#1 is: 4
    Number#2 is: 6

After Swapping:-
    Number#1 is: 6
    Number#2 is: 4

I have different approach.

You can keep your two values in a Pair. Then you can do this:

fun <T> swap(pair: Pair<T, T>): Pair<T, T> {
    return Pair(pair.second, pair.first)
}

and you use it like this:

var pairOfInts = Pair(1, 2)
println("first: ${pairOfInts.first}") // prints 1
println("second: ${pairOfInts.second}") // prints 2

pairOfInts = swap(pairOfInts)

println("first: ${pairOfInts.first}") //prints 2
println("second: ${pairOfInts.second}") //prints 1

In order to use Kotlin List you could create this kind of extension. It returns a copy of this list with elements at indices a and b swapped.

fun <T> List<T>.swap(a: Int, b: Int): List<T> = this
    .toMutableList()
    .also {
        it[a] = this[b]
        it[b] = this[a]
    }

If you use an array, you can use this:

fun <T> Array<T>.swap(i: Int, j: Int) {
    with(this[i]) {
        this@swap[i] = this@swap[j]
        this@swap[j] = this
    }
}
Related