Kotlin 迭代一个集合并将某个值映射到新映射

时间:2021-03-07 20:25:25

标签: kotlin

我有一张收藏地图。我需要从中获取 id 列表..

val m1 = mapOf("id" to 1, "name" to "Alice")
val m2 = mapOf("id" to 2, "name" to "Bob")
val m3 = mapOf("id" to 3, "name" to "Tom")
val nameList = listOf(m1, m2, m3)

结果应该是[1, 2, 3]

2 个答案:

答案 0 :(得分:4)

假设您想要根据示例的列表,而不是根据标题的地图,我会这样做:

val result = nameList.map {
    it.getValue("id").also { id ->
        require(id is Int) { "id must be an Int" }
    } as Int
}

这样做的好处是可以干净地处理以下错误:

  • 缺少 id 键:NoSuchElementException: Key id is missing in the map
  • id 值不是 IntIllegalArgumentException: id must be an Int

答案 1 :(得分:3)

首先,我相信如果可以的话,应该使用类而不是映射来存储像这样的异构数据。因此,您可以使用:

,而不是您的地图
data class Person(val id: Int, val name: String)

val m1 = Person(id = 1, name = "Alice")
val m2 = Person(id = 2, name = "Bob")
val m3 = Person(id = 3, name = "Tom")
val list = listOf(m1, m2, m3)

val idsList = list.map { it.id } // no error handling required, rely on the type system

现在,如果您真的想使用这样的地图,您有多种选择。

如果您确定 id 键将存在且其值为 Int,您可以使用以下内容:

nameList.map { it["id"] as Int }

如果 NullPointerException 不存在于其中一张地图中或 id,如果它不是 ClassCastException,这将失败。

通常,您应该确保您的地图在创建时与您的合同匹配,而不是在访问此类信息时。 但是如果你因为某种原因需要在这里处理错误,你可以使用下面的代替:

Int

nameList.map { (it.getValue("id") as? Int) ?: error("'id' is not an Int") } getValue 缺少键而失败,而 NoSuchElementException 调用因 error() 而失败。您还可以使用 IllegalStateExceptionthrow 使用其他类型的异常。

如果您只想忽略没有有效整数 require() 的条目,您可以使用以下内容:

id

如果您想忽略没有 nameList.mapNotNull { it["id"] as? Int } 的条目,但在那些具有非整数 id 的条目上失败,您可以使用:

id

这最后两个示例依赖于 nameList.mapNotNull { map -> map["id"]?.let { id -> (id as? Int) ?: error("'id' is not an Int") } } ,如果元素的映射值为 mapNotNull,它将过滤掉元素。