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?
No need a swap function in Kotlin at all. you can use the existing also function, for example:
var a = 1
var b = 2
a = b.also { b = a }
println(a) // print 2
println(b) // print 1
If you want to write some really scary code, you could have a function like this:
inline operator fun <T> T.invoke(dummy: () -> Unit): T {
dummy()
return this
}
That would allow you to write code like this
a = b { b = a }
Note that I do NOT recommend this. Just showing it's possible.
Edit: Thanks to #hotkey for his comment
I believe the code for swapping two variables is simple enough - not to try simplifying it any further.
The most elegant form of implementation IMHO is:
var a = 1
var b = 2
run { val temp = a; a = b; b = temp }
println(a) // print 2
println(b) // print 1
Benefits:
The intent is loud and clear. nobody would misunderstand this.
temp will not remain in the scope.
Kotlin encourages the use of immutable data when possible (such as using val instead of var). This greatly reduces the change for subtle bugs, since it's possible to reason more soundly about code if values don't change.
Swapping two values is very much the opposite of immutable data: Did I mean the value of a before or after the swap?
Consider rewriting your code in the following immutable way:
val a = 1
val b = 2
val (a2, b2) = b to a
This works by making use of destructuring declarations, along with the built-in to extension function that creates a Pair.
That is a good usage for with:
var a = 1
var b = 2
with(a) {
a = b
b = this
}
println(a) // 2
println(b) // 1
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
I want to create a mutable map whose keys fall in a continuous range, and values initially set to the same value 9 in a single line using Kotlin. How to do that?
One more option not mentioned in the other answers is to use the associate* function that takes the argument collection that it will put the pairs to:
val result = (1..9).associateWithTo(mutableMapOf()) { 9 }
Unlike .associateWith { ... }.toMutableMap(), this doesn't copy the collection.
If you need to use a different implementation (e.g. a HashMap()), you can pass it to this function, like .associateWithTo(HashMap()) { ... }.
Many collection processing functions in the Kotlin standard library follow this pattern and have a counterpart with an additional parameter accepting the collection where the results will be put. For example: map and mapTo, filter and filterTo, associate and associateTo.
If you mean values, you can use the withDefault function on any Map / MutableMap:
(Playground)
fun main() {
val map = mutableMapOf<String, Int>().withDefault { 9 }
map["hello"] = 5
println(map.getValue("hello"))
println(map.getValue("test"))
}
You can try the following:
val map = object : HashMap<Int, Int>() {
init {
(1..10).forEach {
put(it, 9)
}
}
}
println(map)
I would use associateWith:
val map = (1..9).associateWith { 9 }.toMutableMap()
println(map) // {1=9, 2=9, 3=9, 4=9, 5=9, 6=9, 7=9, 8=9, 9=9}
It also works with other types as key, like Char:
val map = ('a'..'z').associateWith { 9 }.toMutableMap()
println(map) // {a=9, b=9, c=9, d=9, e=9, f=9, g=9, h=9, i=9}
You can use the following way:
import java.util.*
fun main(args: Array<String>) {
val a :Int = 0
val b :Int = 7
val myMap = mutableMapOf<IntRange, Int>()
myMap[a..b] = 9
myMap.toMap()
println(myMap) //Output: {0..7=9}
}
I want to return multiple values from a function. As suggested by another SO answer, I used Destructuring with public class, but the problem is I can't assign the returned destructured result to already existing variables.
data class Result(val res1 :Int, val res2: Int)
class test{
fun retresult():Result{
return Result(2,2)
}
}
fun main(args: Array<String>) {
var var1:Int = 0
var var2:Int = 0
var des = test()
//(var1, var2) = des.retresult() this doesn't work
var1 = des.retresult().res1
var2 = des.retresult().res2 // **works but calls function twice**
}
I don't want to initialize local vals at return point like
val (var1, var2) = des.retresult()
You can assign these two variables without calling the function twice, using with:
fun main(args: Array<String>) {
var var1:Int = 0
var var2:Int = 0
var des = test()
with (des.retresult()) {
var1 = res1
var2 = res2
}
}
Alternatively, your function could take function arguments for setting the results, and then you can pass the setters for these properties. This wouldn't work for local variables, only member properties. If you use C, this is kind of like passing a pointer to a function so it can directly modify a variable rather than returning something.
class Test (var one: Int, var two: Int)
fun doSomething(result1: (Int) -> Unit, result2: (Int) -> Unit) {
result1(2)
result2(2)
}
fun main() {
val test = Test(1, 1)
doSomething(test::one::set, test::two::set)
}
There's an open (and mostly forgotten, it seems) feature request for what you suggested, destructuring assignment to existing variables.
In Kotlin sequences have a takeWhile function that will let you take items as long as they adhere to a given predicate. What I'd like to do is take items according to that predicate, use them in some way, then alter the predicate and take the next "batch". So far I haven't really found a way of doing this purely with what sequences and iterators offer.
Following snippet of code illustrates the problem. The primeGenerator() function returns a Sequence of prime (Long) numbers. Suppose that I want to make lists with each list having prime numbers with the same number of digits. On creating each list I'd use it for some purpose. If the list conforms to what I was searching the iteration can end, otherwise move onto the next list.
val primeIt = primeGenerator().iterator()
var digits = 1
var next: Long? = null
val currentList = ArrayList<Long>()
while (digits < 4) {
next?.also { currentList.add(it) }
next = primeIt.next()
if (next.toString().length > digits) {
println("Primes with $digits: $currentList")
currentList.clear()
digits++
}
}
In this case it ends once the number of digits exceeds 3. This works fine, but I was wondering if there is some way to achieve the same with operations chained purely on the sequence or an iterator of it. Basically chunking the sequence but based on a predicate rather than a set size. The prime number example above is just for illustration, I'm after the general principle, not something that'd only work for this case.
There are no such functions in standard library for large (or infinite) sequences, but you may write such function by yourself (although it requires some extra code):
class BufferedIterator<T>(private val iterator: Iterator<T>) : Iterator<T> {
var current: T? = null
private set
var reachedEnd: Boolean = false
private set
override fun hasNext(): Boolean = iterator.hasNext().also { reachedEnd = !it }
override fun next(): T = iterator.next().also { current = it }
}
fun <T> Iterator<T>.buffered() = BufferedIterator(this)
fun <T> BufferedIterator<T>.takeWhile(predicate: (T) -> Boolean): List<T> {
val list = ArrayList<T>()
if (reachedEnd) return list
current?.let {
if (predicate(it)) list += it
}
while (hasNext()) {
val next = next()
if (predicate(next)) list += next
else break
}
return list
}
fun main() {
val sequence = sequence {
var next = 0
while (true) {
yield(next++)
}
}
val iter = sequence.iterator().buffered()
for (i in 0..3) {
println(iter.takeWhile { it.toString().length <= i })
}
}
With this approach you can easily work even with infinite sequences.
I believe there is a way to accomplish what you want using the standard library. Limit the sequence first and then groupBy the number of digits.
val Int.numberOfDigits
get() = this.toString().length
sequenceOf(1,22,333).takeWhile{ it.numberOfDigits < 3 }.groupBy{ it.numberOfDigits }.values
If you want to avoid the eager evaluation of groupBy you could use groupingBy instead and then reduce potentially leaving the accumulator blank.
ardenit's answer seems like the best reusable approach. Since taking "chunks" of a sequence requires some state it doesn't seem likely something easily done in a purely functional manner. Delegating the state to a separate class enveloping the sequence makes sense.
Here's a small snippet showing what I ended up using. This assumes the sequence will not be empty and is (technically) infinite or further results aren't requested at some point.
class ChunkedIterator<T>(seq: Sequence<T>) {
private val it = seq.iterator()
var next: T = it.next()
fun next(predicate: (T) -> Boolean): List<T> {
val result = ArrayList<T>();
while (predicate.invoke(next)) {
result.add(next)
next = it.next();
}
return result
}
}
one way you could achieve this is by getting an iterator from your your original sequence and then building a new sequence out of it for each "take" -
val itr = seq.iterator()
val batch1 = itr.asSequence().takeWhile { predicate1(it) }.toList()
val batch2 = itr.asSequence().takeWhile { predicate2(it) }.toList()
The Idioms section of the official Kotlin docs contains this example:
Builder-style usage of methods that return Unit
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
As the function apply returns the generic type, and I thought Unit is as same as void in Java, this section is suggesting we can use a void method in builder-style? That doesn't make sense to me - what's it trying to say?
The point it's trying to make is that if you just did traditional Java builder style, like this:
return IntArray(size)
.fill(-1)
then it wouldn't compile, because it's of type Unit, not IntArray.
So traditionally, you'd have to do something like this:
val ret = IntArray(size)
ret.fill(-1)
return ret
apply enables you to avoid this, because the return type is still of type IntArray (or T, in general).
Take this one:
class X {
var a: Int? = null
var b: Int? = null
fun first(a: Int) = apply { this.a = a }
fun second(b: Int) = apply { this.b = b }
}
X().first(2).second(3)
The apply functions are used to return the instance of X after setting the property. This enables builder-style call of both methods. If apply were removed, the function would return Unit.
I can think on some dirty ways to calculate a moving average on Kotlin, but I'm not sure which one is the best. I know that kotlin has a lot of interesting features to work with collections and list. What do you think is the most efficient (or simplest) way to calculate a moving average?
Kotlin 1.2 will introduce a sliding window which you can combine with average obviously.
val data = listOf(1,2,5,6,2,7,8,5,9)
// 3 "period" moving average
val movingAverage = data.windowed(3,1,List<Int>::average)
// OR
val movingAverage = data.windowed(3,1) { it.average() }
Until then you would have to introduce your own sliding sequence.
class SlidingSequence<out T>(val source: Iterable<T>,
val slideSize: Int,
val slideStep: Int) : Sequence<List<T>> {
override fun iterator(): Iterator<List<T>> = object : AbstractIterator<List<T>>() {
private val iterator = if (slideSize > 0) source.iterator() else emptyList<T>().iterator()
private var buffer = listOf<T>()
override fun computeNext() = when {
iterator.hasNext() -> {
buffer = buffer.drop(slideStep).let {
it + iterator.asSequence().take(slideSize - it.size)
}
setNext(buffer)
}
else -> done()
}
}
}
fun <T> Iterable<T>.windowed(size: Int,
step: Int = 1): Sequence<List<T>> {
return SlidingSequence(this, size, step)
}
// and then you can do
val data = listOf(1,2,5,6,2,7,8,5,9)
// 3 "period" moving average
val movingAverage = data.windowed(3).map(List<Int>::average)
PS. I haven't looked at the code of Kotlin 1.2 windowed implementation, but since the function takes an immediate transform, I'm guessing the result is not lazy, where in the self implemented case above it's a lazy result, so you need to actually enumerate the sequence with something like .toList() to get the actual values.
Another one-line given period > 0 is:
data?.takeLast(period)?.reduce { v, d -> v + d}?: 0 / period
This also works if the data is empty or null due to takeLast() `s behaviour.