0

I'm newbie to Kotlin, and new to programming also, so pls be gentle :)

Let's say I have a string (it was optimized to NOT have any duplicated character), i want to compare all characters in that string to the alphabet, which declared as a mutable List of character. I want to delete any character from the alphabet which show up in the string. My code is as below

var alphabet=mutableListOf('a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z') 
    var key="keyword"
    println(key)    
    for (i in key.indices)
        {for (j in alphabet.indices)
             {if (key[i] == alphabet[j])
                  alphabet.removeAt(j)     // 1. this line have error
                  //print(alphabet[j])  //2. but this line runs fine
}}}

In above code, I have error at the "alphabet.removeAt(j)" command, so I try another command to print out the characters instead of delete them, and it runs fine. I read some articles and I know this error related to the invalid index, but I used the "indices" key and I think it's pretty safe. Pls help

3 Answers 3

2

It is safe to iterate using alphabet.indices, but it is not safe to iterate over a collection while modifying it. Note that indices returned indices for a full alphabet, but then you removed some items from it, making it shorter, so indices are no longer valid.

You don't need to iterate over a collection to find an item to remove. You can just do:

alphabet.remove(key[i])

But honestly, you don't need to do anything of this. Your problem is really a subtracting of two sets and you can solve it much easier:

('a'..'z').toSet() - "keyword".toSet()
Sign up to request clarification or add additional context in comments.

4 Comments

I was going to suggest sets as well, but then I thought that sets destroy the order, so might not be as suitable. And now I realised that toSet actually creates a set that does maintain the iteration order. Silly me, I guess. +1
Yes, apparently Kotlin team decided to use linked sets and maps by default, so functions like toSet(), toMap(), setOf(), mapOf(), etc. keep the order. I guess overhead of linked collections is negligible and people often expect that order is preserved, so it makes sense to make them default.
Wow briliant, so so many thing I still need to learn. I've read some tutorials (mostly translated to my language) but barely seen these kind of codes, so simple yet powerful. Thank you guys
@crazydog The important thing is always to start by focusing on what you ultimately want to achieve — in plain English if that helps — before you think about how to do it. Else your thoughts can get stuck on technical details, and miss much simpler approaches. An expressive language like Kotlin gives you many powerful tools, so you rarely need to do manual iteration and suchlike; and a simpler approach will be easier to read and understand and less likely to have bugs.
1

You could simplify that whole loop to just:

alphabet.retainAll{ it !in key })

or

alphabet.retainAll { !key.contains(it) }

or if you want the filtered list to be a new list rather than doing it in-place:

val filtered = alphabet.filter { it !in key }

Comments

1

but I used the "indices" key and I think it's pretty safe

Well, the indices collection is only evaluated once when a loop is entered, not at the start of each iteration. Even if you change the size of alphabet in the inner loop, the inner loop will still loop the same number of times, because it doesn't evaluate alphabet.indices again. It would only do that again on the next iteration of the outer loop, but your code would throw an exception before that point.

Other than decreasing j whenever you remove an item, you can also solve this by

key.forEach(alphabet::remove)

1 Comment

@crazydog If you think an answer answers your question, please consider accepting it by clicking on that checkmark!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.