kotlin merge two maps by overwriting values - kotlin

If I have the below two maps:
val x = mapOf("a" to 10, "b" to 5)
val y = mapOf("a" to 4)
val result = //
How can I get the result to be: {a=4, b=5}? I want the value to be overwritten if the key exists.

val result = x + y does exactly what you need, the second parameter (y) will overwrite the values with the same keys from the first parameter (x)

val result = x.toMutableMap().apply { putAll(y) }

Related

Two sum in kotlin

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:
Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:
Input: nums = [3,3], target = 6
Output: [0,1]
I am adding piece of code.
fun main() {
// val nums = intArrayOf(2, 7, 11, 15)
// val target = 9
val nums = intArrayOf(3, 2, 4)
val target = 6
// val nums = intArrayOf(3, 3)
// val target = 6
twoSum(nums, target).forEach {
print(" $it")
}
}
fun twoSum(nums: IntArray, target: Int): IntArray {
val map = mutableMapOf<Int, Int>()
nums.forEachIndexed { index, i ->
map[i]?.let {
return intArrayOf(it, index)
}
map[target - i] = index
}
return intArrayOf()
}
My youtube link is described that I am debugging the code. My question is how
map[i]?.let {
return intArrayOf(it, index)
}
is going inside the 1st and 2nd iteration of return statment and it not going in 3rd iteration. Can anyone help me on this. Thanks

Is this how I initialize a list with values in Kotlin?

I want to store a number of counts per value, something like this:
value count
0 -> 6
1 -> 2
2 -> 0
3 -> 7
As shown in the example, the values start at 0 and are consecutive integers.
I want to initialize all counts with 0, so that I can then increment them.
This is what I came up with:
val histogram = Array(numBuckets) { 0 }.toMutableList() as ArrayList
histogram[2]++
It works, but the initialization feels a bit convoluted. Is there a better way? Is the ArrayList the correct collection for the job in the place?
You can just use the MutableList constructor:
val histogram = MutableList(numBuckets) { 0 }
Kevin Coppock's answer works well if the values in the value-count pairs are consecutive and starting at 0. Then the array or list index stands for the value in the value-count pair.
If more flexibility is needed, for example if the values
do not start at zero,
have a step which is not 1,
or have irregular steps (e.g. logarithmic),
it might make sense to introduce pairs, either as Pair<Int, Int> or in the form of a data class:
import kotlin.math.pow
data class HistogramEntry(
var value: Int,
var count: Int
)
Example:
val numBuckets = 5
val regularHistogram = List(numBuckets) { HistogramEntry(it, 0) }
regularHistogram[2].count++
regularHistogram(::println)
Output:
HistogramEntry(value=0, count=0)
HistogramEntry(value=1, count=0)
HistogramEntry(value=2, count=1)
HistogramEntry(value=3, count=0)
HistogramEntry(value=4, count=0)
Another example:
val numBuckets = 5
val logarithmicHistogram = List(numBuckets) { HistogramEntry(10f.pow(it + 1).toInt(), 0) }
logarithmicHistogram[2].count = 12345
logarithmicHistogram.forEach(::println)
Output:
HistogramEntry(value=10, count=0)
HistogramEntry(value=100, count=0)
HistogramEntry(value=1000, count=12345)
HistogramEntry(value=10000, count=0)
HistogramEntry(value=100000, count=0)
And of course a HistogramEntry list could also be built manually:
val list = listOf(
HistogramEntry(value = 234, count = 0),
HistogramEntry(value = 36, count = 0),
HistogramEntry(value = 9, count = 0),
HistogramEntry(value = 178, count = 0),
HistogramEntry(value = 11, count = 0)
)

Split a list into three in Kotlin

I have the following data class:
data class Foo(val a: Int = 0, val b: Int = 0)
I have a list of Foo's with the following structure:
[ Foo(a = 1), Foo(a = 2), ..., Foo(b = 22), Foo(a = 5), Foo(a = 6), ... ]
(a group of items with a's, then one b, then a's again)
I would like to split above list into three sub-lists like that:
[ Foo(a = 1), Foo(a = 2), ...]
[ Foo(b = 22) ]
[ Foo(a = 5), Foo(a = 6), ...]
sublist of elements that have non-zero a property
list of one element that has non-zero b
remaining sublist of elements that have non-zero a property
Is it possible to achieve using groupBy or partition?
It is not possible to do it via groupBy or partition, because it is not possible to check the past state in those operations. However, you can do it via a fold operation and using mutable lists. Not sure if it fits to your needs but here it goes:
val input = listOf(Foo(a = 1), Foo(a = 2), Foo(b = 22), Foo(a = 5), Foo(a = 6))
val output: List<List<Foo>> = input.fold(mutableListOf<MutableList<Foo>>(mutableListOf())) { acc, foo ->
val lastList = acc.last()
val appendToTheLastList =
lastList.isEmpty() ||
(foo.a != 0 && lastList.last().a != 0) ||
(foo.b != 0 && lastList.last().b != 0)
when {
appendToTheLastList -> lastList.add(foo)
else -> acc.add(mutableListOf(foo))
}
return#fold acc
}
println(output)
outputs:
[[Foo(a=1, b=0), Foo(a=2, b=0)], [Foo(a=0, b=22)], [Foo(a=5, b=0),
Foo(a=6, b=0)]]
Note: I have to point out that this solution is not better than a solution with regular loops.
So you want to 1) ignore the first Foos where a=0, 2) start collecting them when you see Foos where a is non-zero, 3) when you hit a Foo where a=0, put that in another list, because b will be non-zero, 4) start collecting non-zero a's again in a third list?
If that's what you want (this is an extremely specific thing you want and you haven't been clear about it at all) you could do it this way:
data class Foo(val a: Int, val b: Int)
val stuff = listOf(Foo(0,1), Foo(1,2), Foo(3,0), Foo(0, 4), Foo(0, 5), Foo(6, 1), Foo(0,7))
fun main(args: Array<String>) {
fun aIsZero(foo: Foo) = foo.a == 0
// ignore initial zero a's if there are any
with(stuff.dropWhile(::aIsZero)) {
val bIndex = indexOfFirst(::aIsZero)
val listOne = take(bIndex)
val listTwo = listOf(elementAt(bIndex))
val listThree = drop(bIndex+1).filterNot(::aIsZero)
listOf(listOne, listTwo, listThree).forEach(::println)
}
}
You can't use partition or groupBy because your predicate depends on the value of a, but also on whether it happens to represent that one element you want to put in the b list, and for the others whether they appear before or after that b element. Which you don't know before you start processing the list.
You could mess around with indices and stuff, but honestly your use case seems so specific that it's probably better to just do it imperatively instead of trying to cram it into a functional approach.

Find the first element in a list that verify a condition

Assuming we are given a list of integers R = [3,5,3,6,0,6,7], an threshold x (integer) and a window size (integer) p. For example, x=4 and p = 2.
I need to find the first index t that verifies the the following conditions:
R[t] >= 4, R[t+1] >= 4. Since p=2, we need to only verify for two boxes t and t+1. If p was equal to 3 we will need to verify for t, t+1 and t+2.
Here the t I am looking for is 5 (indexing is starting from 0).
How to write this in a elegant way in Kotlin (rather than looping on the elements).
A tentative that is giving an error (x=4 and p = 2. The output should be 3 since we start indexing by 0):
val numbers = listOf(1, 2, 3, 4, 6, 8, 2)
val firstIndex = numbers.find { it >= 4 for it in it..it+2-1}
val numbers = listOf(1, 2, 3, 4, 6, 8, 2)
val p = 2
val x = 4
val t = numbers.windowed(p).indexOfFirst { window -> window.all { it >= x } } // t == 3
t will be equal to -1 in case if no matches will be found
Use windowed to check groups of values for each index in the list. Use withIndex() so you are iterating with the indices, which you need in your final result. Then use firstOrNull() (which find() is a redundant alias of). And finally, take ?.index to get the index of the first entry that satisfies the condition, or null if none satisfy.
val x = 4
val p = 3
val list = listOf(2,5,3,6,0,6,7)
val t = list
.windowed(p)
.withIndex()
.firstOrNull { (_, sublist) -> sublist.all { it >= x } }
?.index
find Returns the first element matching the given predicate, or null if no such element was found.
If I've understood correctly, this should work:
fun main() {
val list = listOf(3,5,3,6,0,6,7)
val p = 2
val x = 4
val t = list.withIndex().windowed(p).firstOrNull() { window ->
window.all { it.value >= x }
}?.first()?.index
println(t)
}
Output:
5

Kotlin - same condition: multiple if statements or one if statement

In Kotlin you can use if statements kind of like ternary operators.
We have the option to do something like this:
val x = if (isOdd) 1 else 2
but if we have multiple variables that need to be set based on some condition is it more correct to do it the old fashioned way like so:
val x: Int
val y: Int
val z: Int
if (isOdd) {
x = 1
y = 3
z = 5
} else {
x = 2
y = 4
z = 6
}
or like this :
val x = if (isOdd) 1 else 2
val y = if (isOdd) 3 else 4
val z = if (isOdd) 5 else 6
the second way looks much cleaner to me, but I'd like to know if the first method would be computed faster since it only needs to calculate the condition once whereas the second way needs to check the condition 3 times.
Is the second way actually slower or will it be optimized by the compiler?
I'd prefer something like this, looks way more Kotlinesque:
data class Point3D(val x: Int, val y: Int, val z: Int)
fun foo(isOdd: Boolean): Point3D = if (isOdd) Point3D(1, 3, 5) else Point3D(2, 4, 6)
//or using destructureing see https://kotlinlang.org/docs/reference/multi-declarations.html)
val (x,y,z) = if (isOdd) Triple(1, 3, 5) else Triple(2, 4, 6)
Also it combines the best of both, using if as expression and only one if is needed. (At the cost of an additional object allocation).
But to answer your question. Do what you like and think is most readable. Performance wise I doubt you will make a difference.
if is an expression in Kotlin, not a statement: it returns a value, whereas it doesn't in Java's case.
I don't think here is such an optimization issue you should ever think about, honestly. Premature optimization is a common source of problems. If this boolean variable is thread-confined, then I think the compiler will perform all the optimizations that are possible in this context, so it will be almost no overhead at all (if not completely).
Wise choice in OO languages is to prefer clearness and flexibility over low-level optimization issues (especially when compilers are able to resolve them).
Okay, so just saw this question again and got curious... So I did some tests.
Turns out there is actually a HUGE difference, heres the results:
Code
fun main() {
for (i in 0 until 3) {
val t1_s = System.currentTimeMillis()
for (j in 0 until 100000) {
when (i){
0 -> a(j % 2 == 0)
1 -> b(j % 2 == 0)
2 -> c(j % 2 == 0)
}
}
val t1_e = System.currentTimeMillis()
println("Test $i - time ${t1_e - t1_s}")
}
}
fun a(isOdd: Boolean): Int {
val x: Int
val y: Int
val z: Int
if (isOdd) {
x = 1
y = 3
z = 5
} else {
x = 2
y = 4
z = 6
}
return x + y + z
}
fun b(isOdd: Boolean): Int {
val x = if (isOdd) 1 else 2
val y = if (isOdd) 3 else 4
val z = if (isOdd) 5 else 6
return x + y + z
}
fun c(isOdd: Boolean): Int {
val (x,y,z) = if (isOdd) Triple(1, 3, 5) else Triple(2, 4, 6)
return x + y + z
}
Output
Test 0 - time 3
Test 1 - time 1
Test 2 - time 8
It seems my second solution is the fastest, my first suggestion next, and the top answer as MUCH slower.
Does any one know why this might be? Obviously these are milliseconds so it almost always wouldn't matter, but it is neat to think that one method is 5-10 times faster
EDIT:
So tried bumptin the iterations up to 100000000 and the results were:
Test 0 - time 6
Test 1 - time 41
Test 2 - time 941
I Guess the first 2 options are getting optimized out but the third option is always creating a new object making it much slow
Try it online!