6

For example, if I have a list of List(1,2,1,3,2), and I want to remove only one 1, so the I get List(2,1,3,2). If the other 1 was removed it would be fine.

My solution is:

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)

But I feel like I am missing a simpler solution, if so what am I missing?

Akavall
  • 82,592
  • 51
  • 207
  • 251

3 Answers3

6

surely not simpler:

def rm(xs: List[Int], value: Int): List[Int] = xs match {
  case `value` :: tail =>  tail
  case x :: tail => x :: rm(tail, value)
  case _ => Nil
}

use:

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)
perreal
  • 94,503
  • 21
  • 155
  • 181
3

you can zipWithIndex and filter out the index you want to drop.

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)

The filter + map is collect,

scala> myList.zipWithIndex.collect { case (elem, index) if index != 0 => elem }
res2: List[Int] = List(2, 1, 3, 2)

To remove first occurrence of elem, you can split at first occurance, drop the element and merge back.

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

Following is expanded answer,

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)

Resource

How to remove an item from a list in Scala having only its index?

How should I remove the first occurrence of an object from a list in Scala?

prayagupa
  • 30,204
  • 14
  • 155
  • 192
  • It seems that there are several approach of removing an element if we know the index, but if we want to remove a specific value once, the best we can do is find an index of that value, and then remove value at that index? – Akavall Jun 03 '17 at 04:17
  • 1
    @Akavall you can split at first occurance with `list.span(_ != elementToRemove)` and drop 1 element and merge together. See the updated answer if that helps – prayagupa Jun 03 '17 at 04:51
1

List is immutable, so you can’t delete elements from it, but you can filter out the elements you don’t want while you assign the result to a new variable:

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)

Rather than continually assigning the result of operations like this to a new variable, you can declare your variable as a var and reassign the result of the operation back to itself:

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)
Andrew Li
  • 55,805
  • 14
  • 125
  • 143
Savan
  • 161
  • 3
  • 11
  • 2
    If I (OP) would apply `filter` to the example, I would filter out both `1`s, and that's not what I want. – Akavall Jun 03 '17 at 04:11