'Kotlin: How to check if enum contains a given String without messing with Exceptions?
Why there is no contains method in enum classes (as well as in Java)? And how to implement it elegantly? Now I'm using this ugly approach:
val contains: Boolean =
try {
MyEnum.valueOf("some string")
true
} catch (e: IllegalArgumentException) {
false
}
Solution 1:[1]
enumContains
You can create an enumContains function similar to Hound Dog's answer but using reified type parameters instead.
You cannot create a JVM independent solution in Kotlin 1.0 but you can in Kotlin 1.1 using enumValues.
Kotlin 1.1
/**
* Returns `true` if enum T contains an entry with the specified name.
*/
inline fun <reified T : Enum<T>> enumContains(name: String): Boolean {
return enumValues<T>().any { it.name == name}
}
Kotlin 1.0
/**
* Returns `true` if enum T contains an entry with the specified name.
*/
inline fun <reified T : Enum<T>> enumContains(name: String): Boolean {
return T::class.java.enumConstants.any { it.name == name}
}
Usage
enumContains<MyEnum>("some string") // returns true or false
enumValueOfOrNull
If you also need the actual enum entry then you might consider creating an enumValueOfOrNull function instead.
Kotlin 1.1
/**
* Returns an enum entry with the specified name or `null` if no such entry was found.
*/
inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
return enumValues<T>().find { it.name == name }
}
Kotlin 1.0
/**
* Returns an enum entry with the specified name or `null` if no such entry was found.
*/
inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
return T::class.java.enumConstants.find { it.name == name }
}
Usage
enumValueOfOrNull<MyEnum>("some string")
Solution 2:[2]
You can just take values Array of your enum and use contains over it. For example:
Planets.values().map { it.name }.contains("EARTH")
But for this you need to have correct string value so you might uppercase it before search.
If you want to find enum by its value take a look at the Reverse Lookup for enums.
Edit:
As @JamesBassett suggested you can optimize it to stop looking once it finds a match.
Planets.values().any { it.name == "EARTH" }
Solution 3:[3]
You could do something like this:
fun <T : Enum<*>> KClass<T>.contains(value: String): Boolean {
return this.java.enumConstants.any { it.name == value }
}
MyEnum::class.contains("some string")
Solution 4:[4]
or if you are really adventurous
enum MyEnum {
MY_1, MY_2;
companion object {
fun isInEnum(someString: String) {
return try {
valueOf(someString)
true
} catch (e: Exception) {
false
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |
| Solution 2 | |
| Solution 3 | James Bassett |
| Solution 4 | kotlinbonanza |
