【问题标题】:Get index of given element from array extension function kotlin从数组扩展函数kotlin获取给定元素的索引
【发布时间】:2021-04-21 07:11:57
【问题描述】:

我想更多地了解 Kotlin 扩展函数,并尝试为 List 实现扩展函数,通过传递位置的值(如果有意义的话)来获取元素的索引。

我有什么:

fun List<String>.getItemPositionByName(item: String): Int {
    this.forEachIndexed { index, it ->
        if (it == item)
            return index
    }
    return 0
}

虽然这很好用,但我也需要为 Int 做同样的事情。 对于我的问题,有没有办法将其组合成一个扩展函数而不是两个单独的扩展函数?我承认这不是很多代码,复制也无妨,但出于兴趣和未来参考。

我知道这个问题Extension functions for generic classes in Kotlin 的响应在哪里——至少据我所知——“不像这样工作,但我真的不需要它来输入类型,而“只需要”用于字符串和诠释。

【问题讨论】:

    标签: kotlin kotlin-extension


    【解决方案1】:

    Kotlin 在一定程度上支持 C++ 人们所说的专业化。它适用于您正在使用的非常基本的类型,因此您所要求的绝对是可能的。

    我们可以声明以下声明。当然,您可以复制代码,然后就可以了。

    public fun List<String>.getItemPositionByName(item: String) = ...
    public fun List<Int>.getItemPositionByName(item: String) = ...
    

    如果您不喜欢重复代码,惯用的方法是使用文件私有函数并简单地委托给私有函数。

    private fun <T> getItemImpl(list: List<T>, item: T): Int {
        list.forEachIndexed { index, it ->
            if (it == item)
                return index
        }
        return -1
    }
    
    public fun List<String>.getItemPositionByName(item: String) = getItemImpl(this, item)
    public fun List<Int>.getItemPositionByName(item: Int) = getItemImpl(this, item)
    

    这限制了getItemImpl,它对您所在的当前文件完全通用,而IntString 专业化在其他任何地方都可以公开使用。

    尝试在不属于List&lt;Int&gt;List&lt;String&gt; 类型的任何列表上调用getItemPositionByName 将失败并出现类型错误。

    Kotlin Playground 链接:https://pl.kotl.in/NvIRXwmpU

    如果您不知道,您正在实现的方法已经存在于标准库中 (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/index-of.html)

    【讨论】:

      【解决方案2】:

      Kotlin 标准库已经有一个执行此操作的函数:indexOf()

      val one = listOf("a", "b", "c").indexOf("b")
      check(one == 1)
      

      一种选择是查看implementation of that function

      还有first() 函数,如果您想编写自己的通用版本,可以使用它:

      fun <T> List<T>.getItemPositionByName(item: T) = withIndex()
          .first { (_, value) -> item == value }
          .index
      
      fun main(args: Array<String>) {
          val one = listOf("a", "b", "c").getItemPositionByName("b")
          check(one == 1)
      }
      

      或者,重写您的原始版本以使用泛型:

      fun <T> List<T>.getItemPositionByName(item: T): Int {
          this.forEachIndexed { index, it ->
              if (it == item)
                  return index
          }
          return 0
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-11
        • 2021-10-25
        • 2021-08-15
        • 2011-04-15
        • 1970-01-01
        • 1970-01-01
        • 2012-11-23
        • 2018-09-28
        相关资源
        最近更新 更多