Kotlin For loop start from a given index - kotlin

I want to start a For loop from a given index
in Java you can easily write
for (int i = startingIndex; i < items.size(); i++)
how to to do that in Kotlin?
I know how to write a for loop in Kotlin
my example
I want to iterate over an array of strings but the start position is 3, not iterating over a Range the iteration will be over a collection of items

For iterating from the start item till the last, you can use something like this:
for (i in startingIndex until items.size) {
//apply your logic
}

Another option is to drop first n elements and use forEach from there:
val l = listOf(1, 2, 3, 4)
l.drop(1).forEach { println(it) } // prints "2, 3, 4"

Instead of iterating over the items in your array, you can iterate over the indices and access the array by index. Here's a simple example.
val otherStrings = arrayOf("a", "b", "c", "d", "e")
for (i in 3..otherStrings.size-1)
println(otherStrings[i])
This iterates from starting index 3 to the last index (which is size - 1)

If the function is repeated several times you could do this:
Create an extension function
List<String>.startByIndex(startingIndex : Int){
for(index in startingIndex until this.size){
//apply common logic
}
}
call the extension function from your string list
var startIndex : Int = 3 // example
items.startByIndex(startIndex)
P.S. : If, for example, the extension function must always return a string as output, you have to change everything like this:
List<String>.startByIndex(startingIndex : Int) : String {
for(index in startingIndex until this.size){
var result : String
//apply common logic and instantiate var result
return result
}
}
var startIndex : Int = 3 // example
var result : String = items.startByIndex(startIndex)

Related

Write a kotlin program that prints the number that is repeated the most in a consecutive way

I'm kind of stuck, I don't know how to make the second loop to start 1 position above the first loop in Kotlin.
I have an array (named myArray) with 10 elements, I need to Write a Kotlin program that prints the number that has the most consecutive repeated number in the array and also prints the number of times it appears in the sequence.
The program must parse the array from left to right so that if two numbers meet the condition, the one that appears first from left to right will be printed.
Longest: 3
Number: 8
fun main() {
val myArray: IntArray = intArrayOf(1,2,2,4,5,6,7,8,8,8)
for((index , value) in myArray.withIndex()){
var inx = index + 1
var count = 0
var longest = 0
var number = 0
for((inx,element) in myArray.withIndex()) {
if(value == element ){
count+=
}
}
if(longest < count){
longest = count
number = value
}
}
}
I'm against just dropping answers, but it is quite late for me, so I'll leave this answer here and edit it tomorrow with more info on how each part works. I hope that maybe in the meanwhile it will help you to gain some idea to where you might be going wrong.
val results = mutableMapOf<Int, Int>()
(0..myArray.size - 2).forEach { index ->
val current = myArray[index]
if (current == myArray[index + 1]) {
results[current] = (results[current] ?: 1) + 1
}
}
val (max, occurrences) = results.maxByOrNull { it.value } ?: run { println("No multiple occurrences"); return }
println("Most common consecutive number $max, with $occurrences occurrences")
Alternatively if the intArray would be a list, or if we allowed to change it to a list myArray.toList(), you could replace the whole forEach loop with a zipWithNext. But I'm pretty sure that this is a HW question, so I doubt this is the expected way of solving it.
myList.zipWithNext { a, b ->
if (a == b) results[a] = (results[a] ?: 1) + 1
}

How to get collection values in Kotlin lambda

I have two collections: A and B. Both of them consist of equal amount of chars. I zip them. Then I need to count pairs of the same elements, like 'A' and 'A'. I need to write a predicate, but I can't find the way to get both elements from a zipped collection.
I've tried something like this:
val num = A.zip(B).count { it.i: Int, it.j:Int -> it.i == it.j}
and this:
val num = A.zip(guess).count { it[0] == it[2] }
But it doesn't work. How can I reach both elements from these sub lists of chars?
I looked into Kotlin official examples but there are only easy ones:
val evenCount = numbers.count { it % 2 == 0 }
In order to deconstruct the resulting Pair given by .zip when using .count, you need to put the "deconstructor" into parentheses.
a.zip(b).count { (aElement, bElement) -> aElemant == bElement }
You could also just ignore that and just access it directly.
a.zip(b).count { it.first == it.second }
If you want to count the pairs of elements in two lists, you're very close. By calling zip you are given a Pair. You can count the resulting list of Pair objects by accessing their first and second parts and seeing if they match (using ==).
// Assumptions...
val a = listOf("A", "B", "D")
val b = listOf("A", "B", "C")
// Count where both elements of the zipped pair match
return a.zip(b).count { it.first == it.second }

What is the function of the * operation in Kotlin?

The Code A is from the offical sample project.
I don't understand what val tasks = remember { mutableStateListOf(*allTasks) } mean, could you tell me ?
BTW, Android Studio give me some information, you can see Image A
Code A
#Composable
fun Home() {
// String resources.
val allTasks = stringArrayResource(R.array.tasks)
val allTopics = stringArrayResource(R.array.topics).toList()
// The currently selected tab.
var tabPage by remember { mutableStateOf(TabPage.Home) }
// True if the whether data is currently loading.
var weatherLoading by remember { mutableStateOf(false) }
// Holds all the tasks currently shown on the task list.
val tasks = remember { mutableStateListOf(*allTasks) }
...
}
Image A
From the documentation of varargs:
When you call a vararg -function, you can pass arguments individually, for example asList(1, 2, 3). If you already have an array and want to pass its contents to the function, use the spread operator (prefix the array with *):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
As you see, it expands an array to multiple values for use in a vararg. If you havd an array containing the elements 1, 2, 3, you can pass *yourArray to a method that is equivalent to yourMethod(1,2,3).
In Kotlin * is the Spread Operator.
From docs :
When you call a vararg -function, you can pass arguments individually, for example asList(1, 2, 3). If you already have an array and want to pass its contents to the function, use the spread operator (prefix the array with *):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
In this case tasks will contain the list of strings from R.array.tasks

Obtain the length of the selected string in kotlin

I want to obtain the index chars or words in a string
for example
tv.text=" hey how are you, are you okay"
val res=tv.text.indexOf('h')
(have any way for put string instead of char?
output res=0
index of return only first char with h but in my tv text I have more h chars
can we return all h chars indexs
You can use filter function to get all the string indices with the required character.
val text = " hey how are you, are you okay"
val charToSearch = 'h'
val occurrences = text.indices.filter { text[it] == charToSearch }
println(occurences)
Try it yourself
And, if you want to search for strings instead of a single character, you can do this:
text.indices.filter { text.startsWith(stringToSearch, it) }
The following should work (you try to find an index if you found one in the previous iteration and you begin the folloing iteration from the previously found character instance plus 1, so that you don't find the same again and again):
fun main() {
val word = " hey how are you, are you okay"
val character = 'h'
var index: Int = word.indexOf(character)
while (index >= 0) {
println(index)
index = word.indexOf(character, index + 1)
}
}
If you want to store the indexes for later usage you can also do the following:
fun main() {
val word = " hey how are you, are you okay"
val character = 'h'
val indexes = mutableListOf<Int>()
var index: Int = word.indexOf(character)
while (index >= 0) {
index = word.indexOf(character, index + 1)
indexes.add(index)
}
println(indexes)
}
If you just want all the indices matching a char you can do this:
text.indices.filter { text[it] == 'h' }
Finding string matches is trickier, you could use Kotlin's regionMatches function to check if the part of the string starting at index matches what you're looking for:
val findMe = "you"
text.indices.filter { i ->
text.regionMatches(i, findMe, 0, findMe.length)
}
You could use a regular expression too, so long as you're careful about validating the search pattern:
Regex(findMe).findAll(text)
.map { it.range.first() } // getting the first index of each matching range
.toList()

Kotlin: How to iterate through a collection from a specific position with indexes (skip N elements with indexes)

I want to iterate a collection of items from a specific position.
Let's say we want to start from center and iterate the whole right part of the array:
int startFrom = arr.length / 2;
for (int i = startFrom; i < arr.length; i++)
{
String.format("Index %d value %s", i, arr[i]);
}
It's important to track real indexes and values during iteration. As an example you are going to implement in-place sorting algorithm
I've tried to do so using drop().withIndexes(), but looks like drop() creates a new collection and I lose information about real indexes.
It could be fixed manually if we create a variable and calculate proper index
val startFrom = inputData.size / 2
for ((i, item) in inputData.drop(startFrom).withIndex()){
val fixedIndex = i + startFrom
println("Index $i, fixed index $fixedIndex value $item")
}
This solution works but I was hopping there is something that can help to avoid introducing a separate fixedIndex variable and handling this problem manually.
Your original try is very close, just a small change makes it work. Reverse the calls of withIndex() and drop(N) putting withIndex first.
If you do not want to copy the collection, you can convert it to a sequence first using asSequence().
for ((index, item) in inputData.asSequence().withIndex().drop(startFrom)) { ... }
The test code:
val sampleData = listOf("a", "b", "c", "d", "e", "f")
val startFrom = sampleData.size / 2
for ((index, item) in sampleData.asSequence().withIndex().drop(startFrom)) {
println("[$index] => $item")
}
outputs:
[3] => d
[4] => e
[5] => f
That's it! The rest of this answer just provides you with alternatives, including a more efficient and Kotlinesque solution of creating your own extension function at the end.
If the copy of the collection is acceptable, you can do the following shorter version. The withIndex does not cause a copy, but the drop(N) does.
for ((index, item) in inputData.withIndex().drop(startFrom)) { ... }
The eager copy or the sequence could be faster, it depends on the size of the collection, your runtime environment, and CPU cache.
You can also use functional forEach instead of the for loop.
sampleData.asSequence().withIndex().drop(startFrom).forEach { (index, item) ->
println("[$index] => $item")
}
Which then brings up the best and most efficient option. Just write an extension function when using an Array or List so that there is no lazy evaluation using wrapper classes nor any copying. Simply a loop calling your lambda with the index and value. Here are the two new extensions that add a new variation of forEachIndexed:
inline fun <T> Array<T>.forEachIndexed(startFrom: Int,
action: (index: Int, item: T)->Unit) {
for (i in startFrom until this.size) {
action(i, this[i])
}
}
inline fun <T> List<T>.forEachIndexed(startFrom: Int,
action: (index: Int, item: T)->Unit) {
for (i in startFrom until this.size) {
action(i, this[i])
}
}
And this can be called simply for any non-primitive array or list:
sampleData.forEachIndexed(startFrom) { index, item ->
println("[$index] => $item")
}
You could do the same if you want a withIndex(startFrom) style method as well. You can always extend Kotlin to get what you want!
If this is what you're missing, the simplest solution in my opinion is to just use a ranged for loop:
val startFrom = arr.size / 2;
for (i in startFrom until arr.size) {
println(String.format("Index %d value %s", i, arr[i]));
}
If you prefer strictly avoiding expressions like arr[i], then you can change your current solution to use a sequence instead.