【问题标题】:Removing items in a MutableList with Kotlin使用 Kotlin 删除 MutableList 中的项目
【发布时间】:2020-06-16 21:45:19
【问题描述】:

我可以有一个类似的列表

 ["1", "2", "3", ".", "4", "."]

在我的分隔符第一次出现后,我希望删除重复项

在我的情况下,上面的列表应该变成

 ["1", "2", "3", ".", "4"]

我想要“.”的所有重复项第一次出现后删除。最好的方法是什么?

【问题讨论】:

  • list.removeAt(list.indexOfLast { it == "." })?

标签: kotlin mutablelist


【解决方案1】:

您可以使用临时的 MutableSet 轻松检查值是否重复。

fun <T> MutableList<T>.removeDuplicates(): Boolean {
    val set = mutableSetOf<T>()
    return retainAll { set.add(it) }
}

解释:MutableList.retainAll 是一个函数,用于删除 lambda 返回 false 的每个项目。将项目添加到 Set 时,如果该项目已存在于 Set 中,则返回 false。因此,每个唯一项目的第一次出现将返回 true,而后续出现将返回 false


编辑:在我看来,也许您只对具有重复项的特定分隔符条目感兴趣。在这种情况下,我会使用布尔值而不是 Set 来跟踪它是否已经找到。我使用removeAll 而不是retainAll 以使其更易于阅读。

fun <T> MutableList<T>.removeDuplicatesOf(delimiter: T): Boolean {
    var firstInstanceFound = false
    return removeAll { it == delimiter && firstInstanceFound.also { firstInstanceFound = true } }
}

解释:removeAll删除任何 lambda 返回 true 的东西。由于逻辑短路,任何不是分隔符的东西都会在到达&amp;&amp; 之后的部分之前返回false。当找到第一个分隔符时,firstInstanceFound 将为 false,因此逻辑语句的计算结果为 false。 also 分支也被命中,因此firstInstanceFound 将适用于任何后续找到的分隔符。

【讨论】:

  • 你能解释一下它是如何工作的吗?我是 Kotlin 的新手,代码看起来很简单。我可以告诉很多事情正在发生
【解决方案2】:

我找到了两种方法。第一个是最'Java':

// Setup values
val list = mutableListOf("1", "2", "3", ".", "4", ".")
val delim = "."

// Check if list is empty
val size = list.size - 1
if (size < 0) return

// Get first delim index
val firstMatch = list.indexOf(delim) + 1
if (firstMatch < 1) return

// Reverse-iterate the list until delim location
for (i in size downTo minOf(firstMatch, size)) {
    if (list[i] == delim) list.removeAt(i)
}

println(list)

这是更小的 Kotlin 风格的解决方案:

val list = mutableListOf("1", "2", "3", ".", "4", ".")
val delim = "."

val firstMatch = list.indexOf(delim)
if (firstMatch < 0) return
val newList = list.filterIndexed { index, s -> s != delim || index == firstMatch }
println(newList)

【讨论】:

    【解决方案3】:

    最简单的方法是使用distinct() 函数,它返回一个没有重复值的列表

    val list = listOf('1', '2', '3', '.', '4', '.')
    println(list.distinct()) // [1, 2, 3, ., 4]
    

    【讨论】:

    • 我不打算删除除了后续的“。”之外的任何内容。在第一个之后
    • distinct() 函数将返回一个没有重复值的列表,因此,您将拥有一个没有后续“。”的列表。在第一个之后,如你所愿。
    • 不知道为什么这个答案被否决了。这没有错。但需要注意的是,这会生成一个新的、单独的 List 实例,并且不会修改原始 MutableList 的内容。
    • 是的,完全有很多方法可以解决这个问题。这是另一个列表,而不是修改现有的列表
    • distinct() 也会删除重复的数字。我的印象是,问题只是删除重复的 . 字符。
    【解决方案4】:

    要删除这些应用循环并将项目添加到新列表中。步骤

    首先将列表转换为可变列表

     val list = listOf("1", "2", "3", ".", "4", ".")
     val mutablelist =list.toMutableList()
    

    在此之后申请循环并将数据存储在新的输出列表中

      val outcominglist= ArrayList<String>()
    
     for(i in list){
        val item = mutablelist[0]
        mutablelist.removeAt(0)
        if(outcominglist.contains(item)){
    
        }
        else{
            outcominglist.add(item)
        }
     }
    

    打印输出列表。

    print(outcominglist)
    

    第二种也是最简单的方法(使用 .distinct 方法)

     val list = listOf('1', '2', '3', '.', '4', '.')
     val newlist =list.distinct()
     print(newlist)
    

    【讨论】:

      【解决方案5】:

      由于您使用的是 Kotlin,因此您拥有不可变数据类型和函数而没有副作用的优势。以下是如何通过使用fold(),在不向外部公开任何状态的函数中使用不可变列表来做到这一点:

      val originalList = listOf("1", "2", "3", ".", "4", ".")
      
      val (filteredList, _) = originalList.fold(
          Pair(emptyList<String>(), false)
      ) { (newList, found), item ->
          if (item == "." && !found) Pair(newList + item, true)
          else if (item == ".") Pair(newList, true)
          else Pair(newList + item, found)
      }
      
      println(filteredList)
      

      结果:

      [1, 2, 3, ., 4]
      

      fold() 获取一个初始累加器值,然后将函数应用于列表的每个元素,同时更新累加器。

      在这里,我们将累加器设置为空列表的 Pair,我们将在其中构建新列表和一个布尔值,以跟踪我们是否已经看到 .

      对于原始列表的每个元素,我们返回一个新的对,将项目添加到新列表(如果需要)并更新我们是否已经看到.newList + item 不会将该项目添加到不可变列表中,它会返回一个新的不可变列表,其中附加了该项目。因为如果我们已经看到 . 作为对的一部分到每次迭代,我们就会传递 Bool 跟踪,因此不需要函数外部的临时变量来跟踪它。

      最后,因为累加值是Pair,所以我们使用destructuring只提取与val (filteredList, _) = pair的pair的累加列表(第一个值)。

      对于您的列表,返回的 Pair 值将如下所示:

      1. ([1], false)
      2. ([1, 2], false)
      3. ([1, 2, 3], false)
      4. ([1, 2, 3, .], true)
      5. ([1, 2, 3, ., 4], true)
      6. ([1, 2, 3, ., 4], true)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-12
        • 1970-01-01
        • 1970-01-01
        • 2020-11-10
        • 1970-01-01
        相关资源
        最近更新 更多