Case insensitive key for hashmap kotlin? - kotlin

I have a hashmap with string as key and integer as value. I want the keys to be case insensitive.
val items = HashMap<String, Int>()
items["key1"] = 90
items["Key1"] = 80
items["C"] = 70
for ((k, v) in items) {
println("$k = $v")
}
This takes key1 and Key1 as separate entries

For this, you would need either to provide some extension function that would put and get the entry in some defined way (e.g. using every time lowercase() String's method) keeping keys case insensitive
fun HashMap<String, Int>.putInsensitive(k: String, v: Int) {
this[k.lowercase()] = v
}
fun HashMap<String, Int>.getInsensitive(k: String, v: Int): Int? = this[k.lowercase()]
or provide your own Map interface implementation (it could even inherit from HashMap)
class InsensitiveHashMap<V> : HashMap<String, V>() {
override fun put(key: String, value: V): V? = super.put(key.lowercase(), value)
override fun get(key: String): V? = return super.get(key.lowercase())
}

Although you can fake this with an extension to HashMap (as mentioned in another answer), I don't think that's a good solution: in order to make the map's behaviour fully consistent, you'd probably need to override lots of methods.  (For example, it would be hard to ensure that it maintained the case-insensitivity if you update the map via its keySet.  And there are probably many more gotchas along the way.)
In most cases, you don't really need a HashMap specifically — you just need a Map implementation.  And so an alternative is to use another type of map that lets you provide your own Comparator, e.g.:
val items = TreeMap<String, Int>{ a, b ->
a.toLowerCase().compareTo(b.toLowerCase())
}
TreeMap is an implementation of SortedMap — a special type of Map that keeps its keys in order: either their natural ordering, or one you provide.  In this case, I've given a simple Comparator implementation which compares the lower-case versions of the two strings.
With this definition, the rest of the code in the question runs fine, and prints out:
C = 70
key1 = 80
…i.e. it has recognised that "Key1" should be treated the same as "key1", and updated that value instead of adding a new one.  I think this is the behaviour you want.
You don't need to take account of the fact that the map is sorted; that's just an added bonus.  You can still treat it like any other Map implementation, and everything should work.
(This is yet another example of why it's better to program to the interface, not the implementation.  If you write code that can use any Map implementation, you can give it a HashMap or a TreeMap or any other sort of map without any changes.)

A variation on the answer by #m.antkowicz, you can actually "override" the get / put operators on HashMap itself (and make it into a fantastic footgun):
operator fun HashMap<String, Int>.get(k: String): Int? = this[k.toLowerCase()]
operator fun HashMap<String, Int>.set(k: String, v: Int): Int? {
val originalK = this[k.toLowerCase()]
this.put(k.toLowerCase(), v )
return originalK
}
So now you can:
fun main() {
val items = HashMap<String, Int>()
items["key1"] = 90
items["Key1"] = 80
items["C"] = 70
for ((k, v) in items) {
println("$k = $v")
}
// Prints:
// key1 = 80
// c = 70
}

Related

How to pass object as argument in Kotlin

I have these two objects A and B I want to use these objects interchangeably in the digit class like shown in this snippet code
internal object A {
internal const val ZERO = "ZERO"
internal const val ONE = "ONE"
}
internal object B {
internal const val ZERO = "ZERO"
internal const val ONE = "UN"
}
class Digit(Lang: String) {
private var X: Any? = null
init {
when (Lang) {
"eng" -> X = A
"fr" -> X = B
}
}
fun spell() {
println(X.ZERO)
}
}
I want inside the Digit class to use both objects, not at the same time, only when I want the English language the Digit class use object A and when I want french language the Digit class use the object B.
I should use reflection? or is there a better design?
The simplest answer is to have your objects all implement the same interface, e.g.:
interface Language {
val ZERO: String
val ONE: String
}
internal object A: Language {
override val ZERO = "ZERO"
override val ONE = "ONE"
}
// …
You can then set a Language reference to any object implementing that interface.
A related (and more concise) approach might be to use an enum:
enum class Language(val ZERO: String, val ONE: String) {
A("ZERO", "ONE"), B("ZERO", "UN")
}
You can then refer to the objects as Language.A &c.
But in practice, none of these approaches scale well. You're likely to end up with a good number of language strings, and probably quite a few languages to support, and those methods will get long-winded. And hard-coding all the strings will make it much more awkward to manage.
So it's more usual to store all the language strings in resource files and load them in at runtime. You could do that manually, e.g. storing the strings in a map — but many platforms and frameworks support standard ways to select the right language, load the strings, and use them. There are many existing questions about this.
data class Translation(val ZERO: String, val ONE: String)
val a = Translation(ZERO = "ZERO", ONE = "ONE")
val b = Translation(ZERO = "ZERO", ONE = "UN")
class Digit(Lang: Translation) {
private val x = Lang
fun spell() {
println(x.ONE)
}
}
Digit(a).spell()
Digit(b).spell()

Providing only one type parameter to an extension function with multiple type parameters in Kotlin

Introduction
In Kotlin I have a generic conversion extension function that simplifies conversion of this object of type C to an object of another type T (declared as the receiver) with additional conversion action that treats receiver as this and also provides access to original object:
inline fun <C, T, R> C.convertTo(receiver: T, action: T.(C) -> R) = receiver.apply {
action(this#convertTo)
}
It is used like this:
val source: Source = Source()
val result = source.convertTo(Result()) {
resultValue = it.sourceValue
// and so on...
}
I noticed I often use this function on receivers that are created by parameterless constructors and thought it would be nice to simplify it even more by creating additional version of convertTo() that automates construction of the receiver based on its type, like this:
inline fun <reified T, C, R> C.convertTo(action: T.(C) -> R) = with(T::class.constructors.first().call()) {
convertTo(this, action) // calling the first version of convertTo()
}
Unfortunately, I cannot call it like this:
source.convertTo<Result>() {}
because Kotlin expects three type parameters provided.
Question
Given above context, is it possible in Kotlin to create a generic function with multiple type parameters that accepts providing just one type parameter while other types are determined from the call-site?
Additional examples (by #broot)
Imagine there is no filterIsInstance() in stdlib and we would like to implement it (or we are the developer of stdlib). Assume we have access to #Exact as this is important for our example. It would be probably the best to declare it as:
inline fun <T, reified V : T> Iterable<#Exact T>.filterTyped(): List<V>
Now, it would be most convenient to use it like this:
val dogs = animals.filterTyped<Dog>() // compile error
Unfortunately, we have to use one of workarounds:
val dogs = animals.filterTyped<Animal, Dog>()
val dogs: List<Dog> = animals.filterTyped()
The last one isn't that bad.
Now, we would like to create a function that looks for items of a specific type and maps them:
inline fun <T, reified V : T, R> Iterable<T>.filterTypedAndMap(transform: (V) -> R): List<R>
Again, it would be nice to use it just like this:
animals.filterTypedAndMap<Dog> { it.barkingVolume } // compile error
Instead, we have this:
animals.filterTypedAndMap<Animal, Dog, Int> { it.barkingVolume }
animals.filterTypedAndMap { dog: Dog -> dog.barkingVolume }
This is still not that bad, but the example is intentionally relatively simple to make it easy to understand. In reality the function would be more complicated, would have more typed params, lambda would receive more arguments, etc. and then it would become hard to use. After receiving the error about type inference, the user would have to read the definition of the function thoroughly to understand, what is missing and where to provide explicit types.
As a side note: isn't it strange that Kotlin disallows code like this: cat is Dog, but allows this: cats.filterIsInstance<Dog>()? Our own filterTyped() would not allow this. So maybe (but just maybe), filterIsInstance() was designed like this exactly because of the problem described in this question (it uses * instead of additional T).
Another example, utilizing already existing reduce() function. We have function like this:
operator fun Animal.plus(other: Animal): Animal
(Don't ask, it doesn't make sense)
Now, reducing a list of dogs seems pretty straightforward:
dogs.reduce { acc, item -> acc + item } // compile error
Unfortunately, this is not possible, because compiler does not know how to properly infer S to Animal. We can't easily provide S only and even providing the return type does not help here:
val animal: Animal = dogs.reduce { acc, item -> acc + item } // compile error
We need to use some awkward workarounds:
dogs.reduce<Animal, Dog> { acc, item -> acc + item }
(dogs as List<Animal>).reduce { acc, item -> acc + item }
dogs.reduce { acc: Animal, item: Animal -> acc + item }
The type parameter R is not necessary:
inline fun <C, T> C.convertTo(receiver: T, action: T.(C) -> Unit) = receiver.apply {
action(this#convertTo)
}
inline fun <reified T, C> C.convertTo(action: T.(C) -> Unit) = with(T::class.constructors.first().call()) {
convertTo(this, action) // calling the first version of convertTo()
}
If you use Unit, even if the function passed in has a non-Unit return type, the compiler still allows you to pass that function.
And there are other ways to help the compiler infer the type parameters, not only by directly specifying them in <>. You can also annotate the variable's result type:
val result: Result = source.convertTo { ... }
You can also change the name of convertTo to something like convert to make it more readable.
Another option is:
inline fun <T: Any, C> C.convertTo(resultType: KClass<T>, action: T.(C) -> Unit) = with(resultType.constructors.first().call()) {
convertTo(this, action)
}
val result = source.convertTo(Result::class) { ... }
However, this will conflict with the first overload. So you have to resolve it somehow. You can rename the first overload, but I can't think of any good names off the top of my head. I would suggest that you specify the parameter name like this
source.convertTo(resultType = Result::class) { ... }
Side note: I'm not sure if the parameterless constructor is always the first in the constructors list. I suggest that you actually find the parameterless constructor.
This answer does not solve the stated problem but incorporates input from #Sweeper to provide a workaround at least simplifying result object instantiation.
First of all, the main stated problem can be somewhat mitigated if we explicitly state variable's result type (i.e. val result: Result = source.convertTo {}) but it's not enough to solve the problem in cases described by #broot.
Secondly, using KClass<T> as result parameter type provides ability to use KClass<T>.createInstance() making sure we find a parameterless constructor (if there's any – if there is none, then result-instantiating convertTo() is not eligible for use). We can also benefit from Kotlin's default parameter values to make result parameter type omittable from calls, we just need to take into account that action might be provided as lambda (last parameter of call) or function reference – this will require two versions of result-instantiating convertTo().
So, taking all the above into account, I've come up with this implementation(s) of convertTo():
// version A: basic, expects explicitly provided instance of `receiver`
inline fun <C, T> C.convertTo(receiver: T, action: T.(C) -> Unit) = receiver.apply {
action(this#convertTo)
}
// version B: can instantiate result of type `T`, supports calls where `action` is a last lambda
inline fun <C, reified T : Any> C.convertTo(resultType: KClass<T> = T::class, action: T.(C) -> Unit) = with(resultType.createInstance()) {
(this#convertTo).convertTo(this#with, action)
}
// version C: can instantiate result of type `T`, supports calls where `action` is passed by reference
inline fun <C, reified T : Any> C.convertTo(action: T.(C) -> Unit, resultType: KClass<T> = T::class) = with(resultType.createInstance()) {
(this#convertTo).convertTo(T::class, action)
}
All three versions work together depending on a specific use case. Below is a set of examples explaining what version is used in what case.
class Source { var sourceId = "" }
class Result { var resultId = "" }
val source = Source()
fun convertX(result: Result, source: Source) {
result.resultId = source.sourceId
}
fun convertY(result: Result, source: Source) = true
fun Source.toResultX(): Result = convertTo { resultId = it.sourceId }
fun Source.toResultY(): Result = convertTo(::convertX)
val result0 = source.convertTo(Result()) { resultId = it.sourceId } // uses version A of convertTo()
val result1: Result = source.convertTo { resultId = it.sourceId } // uses version B of convertTo()
val result2: Result = source.convertTo(::convertX) // uses version C of convertTo()
val result3: Result = source.convertTo(::convertY) // uses version C of convertTo()
val result4: Result = source.toResultX() // uses version B of convertTo()
val result5: Result = source.toResultY() // uses version C of convertTo()
P.S.: As #Sweeper notices, convertTo might not be a good name for the result-instantiating versions (as it's not as readable as with basic version) but that's a secondary problem.

Kotlin Generics - It is possible get integer position of an element of whatever type passed like ordinals method does for Enum defined classes?

There's an already built in way that fulfill my request?
I know Set are unordered
I need to do a vector based Set.
I need to know the position of any value of a generic type to place them in the corresponding index of the array, So I can avoid duplications of the elements.
I'm not ordering or defining an order of the Set.
I don't have any operators that missbehave or break any Set Costraint
Please note that I know this implementation is not efficient for any types that seems infinite like Integers.
I need to do it for an educational purpose.
I have already implemented List Ordered and Hash Table based ones.
For now I have this class, that works flawlessy:
package ads
class MySet<E : Enum<E>> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(eelement : E) : Int{
return eelement.ordinal
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: E){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSet
enum class MyColors{
Red,
Green,
Blue,
Yellow,
Black,
Mint;
}
fun main() {
val myfavc = RawSet<MyColors>()
val yourfavc = RawSet<MyColors>()
//Following operations...
myfavc.insert(MyColors.Red)
yourfavc.insert(MyColors.Blue)
}
I need now to make another class in the same way but working with whatever abstract type already defined in kotlin.
package ads
class MySet<T> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(telement : T) : Int{
/*
For any abstract type return the order of any element
checks if the integer is not greater than maxSet otherwhise it
throws an Exception or manages this istance in other way
*/
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: T){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSeT
//Istance using Int
fun main() {
val myfav = RawSet<Int>()
val yourfav = RawSet<Int>()
//Following operations...
myfav.insert(11)
yourfav.insert(123)
}
I guess there's no built-in way to do so in a generic way.
but I'm still learning kotlin, so maybe I'm missing something useful.
I'm not asking to do my paper.
I don't need a full alternative solutions that I should find out by myself but
I'm opened to read about any tips or resources that can help me to clarify how abstract types works in Kotlin(or Programming Languages) infos like :
How are ordered.
If any value of any type can be compared based on their position
(like c > a for chars).
Range of values/Max values represented for any "apparently
infinite" type like Integers.
Thanks you!
P.S. = Please consider that I'm not an english native, be patient!
Enums are implicitly ordered in declaration order and amount of instances of each enum is finite, so they could be ordered globally and their ordinal could be represented as Int.
Ints (as well as Bytes and Chars) are naturally ordered and have ranges (Int.MIN_VALUE..Int.MAX_VALUE, etc.), so each of them could have an ordinal represented as Int too.
All types implementing Comparable interface could be compared in pairs and any subset of their instances could be ordered, but it doesn't mean that each of them have some global Int ordinal among all possible instances, because set of Ints is finite (2^32 items), and set of all unique instances of generic type T could be countably infinite (like BigInteger) or even uncountable (like Double) (see wiki about cardinality).
All other types couldn't be even compared in pairs (without respectful Comparator<T>).
So you need to manually limit instances of each T that are about to be added in your set and either maually order them or provide respectful Comparator<T> to construct a Map<T, Int> which you'll need to use for subsequent ordinal evaluation:
class SetOfSomehowOrderedInstancesOfType<T>(private val order: Map<T, Int>) {
private val maxSet = order.size
private var myset = BooleanArray(order.size)
private fun getOrdinal(eelement: T): Int {
return order[eelement] ?: throw RuntimeException("Order unknown")
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
Usage:
fun main() {
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInMyFavouriteOrder.mapToIndex())
myfavc.insert(99.2123) //will be inserted with ordinal = 0
val myFavouriteRealNumbersInNaturalOrder = myFavouriteRealNumbersInMyFavouriteOrder.sorted()
val yourfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInNaturalOrder.mapToIndex())
yourfavc.insert(99.2123) //will be inserted with ordinal = 3
}
Alternatively you may define Orderable and Ordinator<T> interfaces (similar to Comparable<T> and Comparator<T>) and determine ordinal using them:
fun interface Ordinator<T> {
fun getOrderOf(x : T) : Int
}
interface Orderable {
val order : Int
}
class MySet<T>(private val ordinator: Ordinator<T>? = null) {
private val maxSet = 127
private var myset = BooleanArray(maxSet)
private fun getOrdinal(eelement: T) = when {
eelement is Orderable -> eelement.order
ordinator != null -> ordinator.getOrderOf(eelement)
else -> throw RuntimeException()
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
Also you may define auxilary function, generalizing previous approach:
fun <T> ordinatorOf(order: List<T>) = object : Ordinator<T> {
private val order = order.mapToIndex()
override fun getOrderOf(x: T) = this.order[x] ?: throw RuntimeException()
}
Usage:
val stringsOrderedByTheirLength = MySet<String> { it.length }
stringsOrderedByTheirLength.insert("aaa") //will be inserted with ordinal = 3
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = MySet(ordinatorOf(myFavouriteRealNumbersInMyFavouriteOrder))
myfavc.insert(99.2123) //will be inserted with ordinal = 0
As somebody pointed out to me that some abstract types representing for an istance Real Numbers can't be done so easily.
The implementation with the enum class works flawlessy but it's been refused from my university professor because I need to use the same syntax for every implementation of the same Data Structure.
Other implementation I have
- HashTableSet<T>
- OrderedListSet<T>
they ask only for an abstract type that can be whatever type, they will work without problem.
I need to do it the same with the
ArraySet<E : Enum<E>>
So if this can't be done easily with Generics, directly...
I'm thinking about mixing them.
Like whatever T type I have
it creates an object called "Domain" so whatever element it insert, before placing them in the array of the set, it place them inside there in a specific order so it simulates what enum it was doing.
I guess that Enumerations can't be defined during the runtime, dinamically.
Then probably I have to define Domain<T> as a private class/object(not sure) that :
Collect the element of the istance of ArraySet(above MySet) inserts with its opeator .insert()
It orders the element comparing to the ones that are already inside
Once is ordered delete all the duples
Re-arrange the whole Boolean Array everytime insert is used based on how Domain grows. (or find out a different algo that partially re-arrange the boolean array)
What do you think?
Advice me more, thanks.

Get index of given element from array extension function kotlin

I'd like to understand Kotlin extension functions more and am trying to implement an extension function for a List, to get the index of an element by passing the value of the position (if that makes sense).
What I have:
fun List<String>.getItemPositionByName(item: String): Int {
this.forEachIndexed { index, it ->
if (it == item)
return index
}
return 0
}
Although this works fine, I would need the same thing for Int too.
To my question, is there a way of combining this into one extension function instead of two seperate ones? I acknowledge that this isn't a lot of code and wouldn't hurt to be duplicated but out of interest and for future references.
I'm aware of this question Extension functions for generic classes in Kotlin where the response is - as I understand it at least - "doesn't quite work like this, but I don't really need it for type but "just" for String and Int.
Kotlin supports what C++ people would refer to as specialization to a certain degree. It works just fine for very basic types like you're using so what you're asking of is definitely possible.
We can declare the following declarations. Of course you could just duplicate the code and you'd be on your way.
public fun List<String>.getItemPositionByName(item: String) = ...
public fun List<Int>.getItemPositionByName(item: String) = ...
If you're not a fan of repeating the code, the idiomatic way would be to make use of file-private functions and simply delegating to the private function.
private fun <T> getItemImpl(list: List<T>, item: T): Int {
list.forEachIndexed { index, it ->
if (it == item)
return index
}
return -1
}
public fun List<String>.getItemPositionByName(item: String) = getItemImpl(this, item)
public fun List<Int>.getItemPositionByName(item: Int) = getItemImpl(this, item)
This limits the getItemImpl which is fully generic to the current file you're in while the Int and String specializations are publicly available anywhere else.
Attempting to call getItemPositionByName on any list which is not of type List<Int> or List<String> will fail with a type error.
Kotlin Playground Link: https://pl.kotl.in/NvIRXwmpU
And just in case you weren't aware, the method you're implementing already exists in the standard library (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/index-of.html)
The Kotlin standard library already has a function that does this: indexOf().
val one = listOf("a", "b", "c").indexOf("b")
check(one == 1)
One option is to look at the implementation of that function.
There is also the first() function, which you could use if you wanted write your own generic version:
fun <T> List<T>.getItemPositionByName(item: T) = withIndex()
.first { (_, value) -> item == value }
.index
fun main(args: Array<String>) {
val one = listOf("a", "b", "c").getItemPositionByName("b")
check(one == 1)
}
Or, rewriting your original version to use generics:
fun <T> List<T>.getItemPositionByName(item: T): Int {
this.forEachIndexed { index, it ->
if (it == item)
return index
}
return 0
}

In Kotlin, how do I idiomatically access nullable nested map values, or return a default?

Quick Kotlin best practices question, as I couldn't really work out the best way to do this from the documentation.
Assume I have the following nested map (typing specified explicitly for the purpose of this question):
val userWidgetCount: Map<String, Map<String, Int>> = mapOf(
"rikbrown" to mapOf(
"widgetTypeA" to 1,
"widgetTypeB" to 2))
Can the following mode be any more succinct?
fun getUserWidgetCount(username: String, widgetType: String): Int {
return userWidgetCount[username]?.get(widgetType)?:0
}
In other words, I want to return the user widget count iff the user is known and they have an entry for that widget type, otherwise zero. In particular I saw I can use [] syntax to access the map initially, but I couldn't see a way to do this at the second level after using ?..
I would use an extension operator method for that.
// Option 1
operator fun <K, V> Map<K, V>?.get(key: K) = this?.get(key)
// Option 2
operator fun <K, K2, V> Map<K, Map<K2, V>>.get(key1: K, key2: K2): V? = get(key1)?.get(key2)
Option 1:
Define an extension that provides get operator for nullable map. In Kotlin's stdlib such approach appears with Any?.toString() extension method.
fun getUserWidgetCount(username: String, widgetType: String): Int {
return userWidgetCount[username][widgetType] ?: 0
}
Option 2:
Create a special extension for map of maps. In my opinion, it is better because it shows the contract of the map of maps better than two gets in a row.
fun getUserWidgetCount(username: String, widgetType: String): Int {
return userWidgetCount[username, widgetType] ?: 0
}