【问题标题】:How to use `filter` on Map instance in Kotlin?如何在 Kotlin 的 Map 实例上使用“过滤器”?
【发布时间】:2016-11-10 17:32:09
【问题描述】:

我看到#filter 是在Map 上定义的,但我不知道如何使用它。有人愿意分享一个例子吗?

我有一个深度嵌套的 TreeMap 实例 (TreeMap<String, Map<String, Map<*, *>>>),我想要 filter/find 第一个(域中唯一的)顶级键,该键具有与更深层次的值相关联的某些特征。

数据如下所示:

{
  "i1": {
    "aliases": {}
  },
  "i2": {
    "aliases": {}
  },
  "i3": {
    "aliases": {}
  },
  "i4": {
    "aliases": {
      "alias-im-looking-for": {}
    }
  }
}

我现在有以下非功能性代码可以解决它:

val indexToAliasMappingType = LinkedTreeMap<String, Map<String, Map<*, *>>>()
val indexToAliasMappings = Gson().fromJson(response.jsonString, indexToAliasMappingType.javaClass)

var currentIndexName = ""
for ((index, aliasMappings) in indexToAliasMappings) {
    val hasCurrentAlias = aliasMappings.get("aliases")?.containsKey(alias)
    if (hasCurrentAlias != null && hasCurrentAlias) {
        currentIndexName = index
    }
}

return currentIndexName

【问题讨论】:

    标签: java functional-programming gson kotlin


    【解决方案1】:

    看起来您需要的是符合您条件的第一个条目的关键部分。像这样的东西(有意单行)应该会有所帮助:

    val currentIndexName = indexToAliasMappings.filterValues { it["aliases"]?.containsKey(alias) ?: false }.keys.firstOrNull() ?: ""
    

    【讨论】:

      【解决方案2】:

      您不能在地图本身上调用firstOrNull,但可以在其entries 集合上调用它:

       val currentIndexName = indexToAliasMappings.entries.firstOrNull {
           it.value["aliases"]?.containsKey(alias) == true
       }?.key
      

      firstOrNull 遍历映射条目并在与谓词匹配的第一个条目处停止。这里不需要像带有filterfilterValues 的变体那样进行中间映射分配。

      【讨论】:

        【解决方案3】:

        .filter 的 lambda 为映射中的每个条目返回一个布尔值。如果该布尔值计算为true,则该条目是返回集合的一部分。如果该布尔值的计算结果为 false,则该条目将被过滤掉。

        val indexToAliasMapping = linkedMapOf(
            "i1" to mapOf(
                "aliases" to mapOf<Any, Any>()
            ),
            "i2" to mapOf(
                "aliases" to mapOf<Any, Any>()
            ),
            "i3" to mapOf(
                "aliases" to mapOf<Any, Any>()
            ),
            "i4" to mapOf(
                "aliases" to mapOf(
                    "aliases-im-looking-for" to "my-alias"
                )
            )
        )
        // If you only need one, you could also use .first instead of .filter, which
        // will give you a Pair<String, Map<String, Map<*, *>>> instead of a List
        val allWithNonEmptyAliases: Map<String, Map<String, Map<*, *>>> = indexToAliasMapping.filter {
            it.value["aliases"]?.containsKey(alias) ?: false
        }
        
        // We use .toList() so you can get the first element (Map doesn't allow you to retrieve by index)
        return allWithNonEmptyAliases.toList().first().first
        

        【讨论】:

          猜你喜欢
          • 2019-07-11
          • 1970-01-01
          • 2018-09-05
          • 2023-02-24
          • 2017-01-22
          • 1970-01-01
          • 1970-01-01
          • 2021-11-12
          • 2015-09-06
          相关资源
          最近更新 更多