代码之家  ›  专栏  ›  技术社区  ›  Quuxplusone

Kotlin:filterNotNull用于映射<K,V?>中的值

  •  0
  • Quuxplusone  · 技术社区  · 5 年前

    以下是我想编写的Kotlin代码(为了清晰起见,添加了额外的类型注释):

    fun test(alpha: String, beta: String, gamma: String? = null, delta: String? = null) {
        val r1: Map<String, String?> =
            hashMapOf(
                "alpha" to alpha,
                "beta" to beta,
                "gamma" to gamma,
                "delta" to delta
            )
        val r2: Map<String, String> = r1.filterValues { it != null }
        callSomeFunction(r2)  // expects a parameter of type Map<String, String>
    }
    

    不幸的是, r1.filterValues { it != null } 还给我一个 Map<String, String?> ,不是a Map<String, String> 我理解为什么会这样;原因是一样的 listOf(1, null).filter { it != null } 具有不同的类型 listOf(1, null).filterNotNull() 然而,我仍然需要解决我的问题!

    是否有一种惯用的方法可以从“filterValuesNotNull” Map ?

    或者,提升一个层次,是否还有其他惯用的方式来表达“给我一个 地图 对于以下参数,但跳过那些值为null的参数“?我可以求助于 this ,但我不想:

    fun test(alpha: String, beta: String, gamma: String? = null, delta: String? = null) {
        var r1: MutableMap<String, String> = mutableMapOf(
            "alpha" to alpha,
            "beta" to beta
        )
        if (gamma != null) {
            r1["gamma"] = gamma
        }
        if (delta != null) {
            r1["delta"] = delta
        }
        callSomeFunction(r1)  // expects a parameter of type Map<String, String>
    }
    
    2 回复  |  直到 5 年前
        1
  •  2
  •   Tenfour04    5 年前

    我认为应该在stdlib中的函数:

    fun <K,V: Any> Map<K,V?>.filterNotNullValuesTo(destination: MutableMap<K,V>): Map<K, V> {
        for ((key, value) in entries) if (value != null) destination[key] = value
        return destination
    }
    
    fun <K,V: Any> Map<K,V?>.filterNotNullValues(): Map<K,V> = filterNotNullValuesTo(mutableMapOf())
    
        2
  •  2
  •   username kipsigman    5 年前

    这里有两种方法,虽然我不知道这两种方法是否地道。

    @Suppress("UNCHECKED_CAST)
    fun filterNotNullUnchecked(map: Map<String, String?>): Map<String, String> =
      map.filterValues { it != null } as Map<String, String>
    

    编辑:正如@Tenfour04所指出的,这并不是不安全的,只是因为类型擦除而未被检查,并添加了一个 Suppress("UNCHECKED_CAST) 注释使警告消失。

    fun filterNotNullUgly(map: Map<String, String?>): Map<String, String> {
      val map2 = HashMap<String, String>()
      for ((k, v) in map) if (v != null) map2[k] = v
      return map2
    }
    
        3
  •  1
  •   Oleg Aleksandrov    5 年前

    嗯,我想,可以这样决定

    val newMap: Map<String, String> = r1.mapNotNull { (key, value) ->
        value?.let { key to it }
    }.toMap()
    
    推荐文章