从Scala列表中删除一个元素

6
例如,如果我有一个列表List(1,2,1,3,2),我只想删除一个1,使得结果为List(2,1,3,2)。如果另一个1被删除了那也没关系。
我的解决方案是:
scala> val myList = List(1,2,1,3,2)
myList: List[Int] = List(1, 2, 1, 3, 2)

scala> myList.patch(myList.indexOf(1), List(), 1)
res7: List[Int] = List(2, 1, 3, 2)

但我感觉还有一种更简单的解决方案,那么我错过了什么吗?

3个回答

6
当然不是更简单:
def rm(xs: List[Int], value: Int): List[Int] = xs match {
  case `value` :: tail =>  tail
  case x :: tail => x :: rm(tail, value)
  case _ => Nil
}

用途:

scala> val xs = List(1, 2, 1, 3)
xs: List[Int] = List(1, 2, 1, 3)

scala> rm(xs, 1)
res21: List[Int] = List(2, 1, 3)

scala> rm(rm(xs, 1), 1)
res22: List[Int] = List(2, 3)

scala> rm(xs, 2)
res23: List[Int] = List(1, 1, 3)

scala> rm(xs, 3)
res24: List[Int] = List(1, 2, 1)

3
你可以使用zipWithIndex方法,再结合filter方法过滤掉要丢弃的索引。
scala> val myList = List(1,2,1,3,2)
myList: List[Int] = List(1, 2, 1, 3, 2)

scala> myList.zipWithIndex.filter(_._2 != 0).map(_._1)
res1: List[Int] = List(2, 1, 3, 2)
filter + map是使用collect函数。
scala> myList.zipWithIndex.collect { case (elem, index) if index != 0 => elem }
res2: List[Int] = List(2, 1, 3, 2)

如果要删除elem的第一次出现,可以在第一次出现处拆分,删除元素,然后合并回去。

list.span(_ != 1) match { case (before, atAndAfter) => before ::: atAndAfter.drop(1) }

以下是详细答案:
val list = List(1, 2, 1, 3, 2)

//split AT first occurance
val elementToRemove = 1
val (beforeFirstOccurance, atAndAfterFirstOccurance) = list.span(_ != elementToRemove)

beforeFirstOccurance ::: atAndAfterFirstOccurance.drop(1) // shouldBe List(2, 1, 3, 2)

资源

如何在 Scala 中仅通过索引删除列表中的项?

如何从Scala列表中删除第一个对象的出现?


似乎有几种方法可以根据索引删除元素,但如果我们想要一次性删除特定的值,最好的方法是找到该值的索引,然后删除该索引处的值? - Akavall
1
@Akavall,你可以使用list.span(_ != elementToRemove)在第一个出现的位置进行分割,然后删除一个元素并合并在一起。如果有帮助,请查看更新后的答案。 - prayagupa

1
列表是不可变的,因此您无法从中删除元素,但是在将结果分配给新变量时,您可以过滤掉不想要的元素:
scala> val originalList = List(5, 1, 4, 3, 2) 
originalList: List[Int] = List(5, 1, 4, 3, 2) 
scala> val newList = originalList.filter(_ > 2) 
newList: List[Int] = List(5, 4, 3)

与其不断将操作结果分配给一个新变量,你可以将变量声明为 var 并将操作的结果重新分配回它自己:
scala> var x = List(5, 1, 4, 3, 2) 
x: List[Int] = List(5, 1, 4, 3, 2) 
scala> x = x.filter(_ > 2) 
x: List[Int] = List(5, 4, 3)

2
如果我(OP)将“filter”应用于示例,我将过滤掉两个“1”,这不是我想要的。 - Akavall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接