I have an enum defined, and I want to get the enum...
# getting-started
c
I have an enum defined, and I want to get the enum from the key that I get from another source (a network response to be exact). The manual mapping seems fine, but is there another way (thats idiomatic) to do this kind of thing?
Copy code
enum class Foo(val key: String, val userName: String) {
  Bar("bar_item", "Bar For You"),
  Baz("baz_item", "Baz For Me"),
  OTHER("other", "Other"),
}

fun getTheFoo(key: String): Foo {
  return when (key) {
    "bar_item" -> Foo.Bar
    "baz_item" -> Foo.Baz
    "other" -> Foo.OTHER
    else -> Foo.OTHER
  }
}
l
return Foo.values().firstOrNull { it.key == key } ?: Foo.OTHER
maybe?
c
Hm yeah. I like that! The firstOrNull makes this apparent that this is just an iterative search. I wonder if theres a better way to structure this data.
e
if there's many elements then
Copy code
private val fooByKey = Foo.values().associateBy { it.key }
fun getTheFoo(key: String): Foo = fooByKey[key] ?: Foo.OTHER
but with 3 I might leave it as an iterative search
c
oooh. associateBy? TIL. Im gonna look into that.
y
FYI, associateBy simply creates a map where the key is provided by your lambda and the value is the items in
Foo.values()
, and so it works just like a normal map.
👍 1
m
if you are willing to adapt the enum constants to be similar or match the received keys, then you could simplify the class and do:
Copy code
enum class Foo(val userName: String) {
  bar_item("Bar For You"),
  baz_item("Baz For Me"),
  other("Other")
}

fun getTheFoo(key: String) = try {
  Foo.valueOf(key)
} catch (e: IllegalArgumentException) {
  Foo.OTHER
}
otherwise if you dislike the try block you could use:
Copy code
fun getTheFoo2(key: String) =
  runCatching { Foo.valueOf(key) }.getOrDefault(Foo.other)
💯 1
m
Yeah, that’s really missing from the standard lib!