Unsolved reference error in copyOfRange - kotlin

I'm trying to copy first 2 elements of my firstArray to my secondArray.
var firstArray = arrayListOf(1,2,3,4)
var secondArray = firstArray.copyOfRange(0,1)
However I'm getting "unsolved reference" error in copyOfRange for some reason.
If I define an Array type for my firstArray I can solve the problem but I don't want to because it can contain different variables in future

The arrayListOf function returns an ArrayList. If this is what you want to use, then you should use the subList function on it:
val firstList = arrayListOf(1, 2, 3, 4)
val secondList = firstList.subList(0, 1)
Note that subList doesn't create a copy, you can make a copy with a toList call, for example:
val secondList = firstList.subList(0, 1).toList()
Or with an explicit call to the ArrayList constructor:
val secondList = ArrayList(firstArray.subList(0,1))
If you want to use an Array instead, use arrayOf and then you can use copyOfRange:
val firstArray = arrayOf(1, 2, 3, 4)
val secondArray = firstArray.copyOfRange(0, 1)

Related

Create list of lists in kotlin?

How do I create a list of lists?
I have a mutable list of ints:
val rsrpList = mutableListOf<Int>()
Now I am trying to create a list of lists, like this:
val rsrpList = mutableListOf<Int>()
val rsrqList = mutableListOf<Int>()
val levelList = mutableListOf<Int>()
val listoflists = List<List<Int>>
listoflists.add(rsrpList)
listoflists.add(rsrqList)
listoflists.add(levelList)
but I know this is wrong, because I'm adding a list one at a time, instead of a list of lists. How would I do this?
You can do this with the Kotlin Standard Library. Both List and MutableList can be created to a specific size (3 in this case) and specify a lambda that will initialize each value.
val listOfList = MutableList(3) { mutableListOf<Int>() }
Or:
val listOfList = List(3) { mutableListOf<Int>() }
Update: To initialize a List with precreated lists:
val listOfList = listOf(list1, list2, list3)
Or in your specific case:
val listOfList = listOf(rsrpList, rsrqList, levelList)
And in both cases you can replace listOf with mutableListOf if you want a mutable list as the main type.
Your example is fine (you have an empty list, you're adding lists to that list, you end up with a list of lists!) but if you're trying to avoid mutability by declaring everything at once:
val listOfLists = listOf(rsrpList, rsrqList, levelList)
and you can declare those lists at the same time if you want
val listOfLists = listOf(
listOf(1, 2, 3),
listOf(9, 8, 7),
listOf(7, 7, 7)
)
or you can use mutableListOf if you need any of them to be mutable! The formatting there isn't necessary, I just think it looks clearer how they're nested

Unresolved reference : removeAt()

I was using the removeAt function and it was just working fine but then suddenly the compiler started to throw the error unresolved reference : removeAt
Here is the code:
fun main() {
val nums = mutableListOf(-3, 167, 0, 9, 212, 3, 5, 665, 5, 8) // this is just a list
var newList = nums.sorted() // this is the sorted list
var finall = mutableListOf<Int>() // this is an empty list that will contain all the removed elements
for(i in 1..3) {
var min: Int = newList.removeAt(0) // element removed from newList is saved from min variable
// above line is producing the error
finall.add(min) // then the min variable is added to the empty list created before
}
println(finall)
println(newList)
}
I have studied a bunch of documentries but I'm unable to find my mistake
The 3rd line, where you sort the list, returns a list not a mutableList. So newList is non-mutable. Replacing that 3rd line with var newList = nums.sorted().toMutableList() will make newList mutable and solve your problem.
The result of nums.sorted() is an immutable list, which means you cannot change it, or in other words, remove elements.
You need to tell kotlin you want a mutable list var newList = nums.sorted().toMutableList()
because newList is List object. List object no method removeAt
you need using newList.toMutableList().removeAt()

Why does Kotlin Nested Lists have this behavior

Take a look at this code example
val list = mutableListOf("1", "2", "3")
val listOfLists = mutableListOf(list, list, list)
val firstList = listOfLists[0] //get reference to *list* variable
firstList[0] = "Hello" // replace "1" in firstList with "Hello"
print(listOfLists)
This is the printed output
[[Hello, 2, 3], [Hello, 2, 3], [Hello, 2, 3]]
If you notice listOfLists variable is never called again in the but it is not being updated. And the update is not just at the first position it is updated at all the position.
My intention is just to update the firstList variable alone.
Why does this happen and how do I go around it?
It's OOP's object behavior man. It affects all the references...
Java handles variables as references and therefore Kotlin as well. Thus all references change after updating one. You'd have to work with copies of the list to ensure these update independently:
val list = listOf("1", "2", "3")
val listOfLists = mutableListOf(
list.toMutableList(),
list.toMutableList(),
list.toMutableList())
val firstList = listOfLists[0]
firstList[0] = "Hello"
print(listOfLists)
Problem
You are putting three references to the same list in another list. Changing the list via one of those references changes the data to which all references point.
Solution
If you don't want that you need to create three independent copies of list for example using the toMutableList() extension function:
val list = mutableListOf("1", "2", "3")
val listOfLists = mutableListOf(
list.toMutableList(),
list.toMutableList(),
list.toMutableList()
)
listOfLists.first()[0] = "Hello"
print(listOfLists)
Output:
[[Hello, 2, 3], [1, 2, 3], [1, 2, 3]]

In Kotlin, how can I take the first n elements of an array

In Kotlin, how can I take the first n elements of this array:
val allColours = arrayOf(
Pair(Color.RED, Color.WHITE),
Pair(Color.RED, Color.BLACK),
Pair(Color.YELLOW, Color.BLACK),
Pair(Color.GREEN, Color.WHITE),
Pair(Color.BLUE, Color.WHITE),
Pair(Color.BLUE, Color.WHITE),
Pair(Color.CYAN, Color.BLACK),
Pair(Color.WHITE, Color.BLACK))
So how can I fill pegColours with the first say 3 Pairs?
var pegColours: Array<Pair<Color,Color>> = //???
I tried allColours.take but it gave an error:
Expecting an element
You need to specify the number of items you want to take.
allColours.take(3)
For a random number of random indices, you can use the following:
val indexes = arrayOf(2, 4, 6)
allColours.filterIndexed { index, s -> indexes.contains(index) }
Note that you can write an extension method for this:
fun <T> Array<T>.filterByIndices(vararg indices: Int) = filterIndexed { index, _ -> indices.contains(index) }
Alternatively, if the indices are consecutive, you can use slice:
allColours.slice(1..3)
The problem with your code that you create pairs with color constants which are Ints (allColours has type Array<Pair<Int, Int>>), but you expect Array<Pair<Color, Color>>. What you have to do is change type pegColours type and use take:
var pegColours: Array<Pair<Int, Int>> = allColours.take(3).toTypedArray()
Also you have to call toTypedArray() cause Array.take returns List rather than Array. Or you can change pegColours type as following:
var pegColours: List<Pair<Int, Int>> = allColours.take(3)
I know you already proposed the usage of take, but alternatively ranges and a simple map also help to write idiomatic code as shown next:
var pegColours = (0 until 3)
.map { allColours[it] }
.toTypedArray()
You are very close :)
val allColours = arrayOf("red", "blue", "green")
kotlin.io.println(allColours.take(2))
Will give you first two elements ["red", "blue"]
You have to specify the number of elements you want to take from the array

How do I create a map from 2 arrays?

I have a string array and an integer array. How do I create a map using the first as keys and the second as values?
val keys = arrayOf("butter", "milk", "apples")
val values = arrayOf(5, 10, 42)
val map: Map<String, Int> = ???
How to convert List to Map in Kotlin? doesn't solve this problem; I have 2 arrays and want a single map.
You can zip together the arrays to get a list of pairs (List<Pair<String, Int>>), and then use toMap to get your map.
Like this:
val keys = arrayOf("butter", "milk", "apples")
val values = arrayOf(5, 10, 42)
val map: Map<String, Int> =
keys.zip(values) // Gives you [("butter", 5), ("milk", 10), ("apples", 42)]
.toMap() // This is an extension function on Iterable<Pair<K, V>>
According to kotlin
Constructing Collections
-> creating a short-living Pair object, is not recommended only if performance isn't critical and to quote: "To avoid excessive memory usage, use alternative ways. For example, you can create a mutable map and populate it using the write operations. The apply() function can help to keep the initialization fluent here."
since I'm not much of an expert I run on to these code and maybe this should work better?:
val numbersMap = mutableMapOf<String,Int>()
.apply{ for (i in 1.. 5) this["key$i"] = i }
println(numbersMap)
//result = {key1=1, key2=2, key3=3, key4=4}
or to adjust it to question above - something like this:
val keys = arrayOf("butter", "milk", "apples")
val values = arrayOf(5, 10, 42)
val mapNumber = mutableMapOf<String, Int>()
.apply { for (i in keys.indices) this[keys[i]] = values[i] }
println(mapNumber)