25

I have a list as follows:

val internalIdList: List[Int] = List()

internalIdList = List(11, 12, 13, 14, 15)

From this list would remove the third element in order to obtain:

internalIdList = List(11, 12, 14, 15)

I can not use a ListBuffer, are obliged to maintain the existing structure. How can I do?

Thanks to all

elm
  • 20,117
  • 14
  • 67
  • 113
YoBre
  • 2,520
  • 5
  • 27
  • 37

7 Answers7

58

There is a .patch method on Seq, so in order to remove the third element you could simply do this:

List(11, 12, 13, 14, 15).patch(2, Nil, 1)

Which says: Starting at index 2, please remove 1 element, and replace it with Nil.

Knowing this method in depth enables you to do so much more than that. You can swap out any sublist of a list with arbitrary other.

Rok Kralj
  • 46,826
  • 10
  • 71
  • 80
  • 3
    I love it! And yeah, I did actually want to "patch" the list rather than just remove an element from it. So I came looking for answers to the wrong question and thanks to you still found solution to my problem. – Peter Perháč Aug 31 '22 at 07:16
22

Simply use

val trunced = internalIdList.take(index) ++ internalIdList.drop(index + 1)

This will also work if index is larger than the size of the list (It will return the same list).

wvdz
  • 16,251
  • 4
  • 53
  • 90
Shadowlands
  • 14,994
  • 4
  • 45
  • 43
  • 3
    The if/else is useless: take and drop will behave as expected if the given index is greater than the size. – Nicolas Sep 18 '13 at 10:02
13

An idiomatic way to do it is to zip the value with their index, filter, and then project the value again:

scala> List(11,12,13,14,15).zipWithIndex.filter(_._2 != 2).map(_._1)
res0: List[Int] = List(11, 12, 14, 15)

But you can also use splitAt:

scala> val (x,y) = List(11,12,13,14,15).splitAt(2)
x: List[Int] = List(11, 12)
y: List[Int] = List(13, 14, 15)

scala> x ++ y.tail
res5: List[Int] = List(11, 12, 14, 15)
Nicolas
  • 24,509
  • 5
  • 60
  • 66
5

If you insist on using the oldschool method, use collect:

List(1,2,3,4).zipWithIndex.collect { case (a, i) if i != 2 => a }

However, I still prefer the method in my other answer.

Rok Kralj
  • 46,826
  • 10
  • 71
  • 80
2

A generic function that implements Nicolas' first solution:

def dropIndex[T](list: List[T], idx: Int): List[T] =
  list.zipWithIndex.filter(_._2 != idx).map(_._1)

Usage:

scala> val letters = List('a', 'b', 'c')
scala> for (i <- 0 until letters.length) println(dropIndex(letters, i))
List(b, c)
List(a, c)
List(a, b)
simleo
  • 2,775
  • 22
  • 23
1
(internalIdList.indices.collect { case i if i != 3 => internalList(i) }).toList

To generalise this...

def removeIndex[A](s: Seq[A], n: Int): Seq[A] = s.indices.collect { case i if i != n => s(i) }

Although this will often return a Vector, so you would need to do

val otherList = removeIndex(internalIdList, 3).toList

If you really wanted a list back.

Shadowlands has a solution which tends to be faster for linear sequences. This one will be faster with indexed sequences.

itsbruce
  • 4,825
  • 26
  • 35
0

Using a for comprehension on a list xs like this,

for (i <- 0 until xs.size if i != nth-1) yield xs(i)

Also consider a set of exclusion indices, for instance val excl = Set(2,4) for excluding the second and fourth items; hence we collect those items whose indices do not belong to the exclusion set, namely

for (i <- 0 until xs.size if !excl(i)) yield xs(i)
elm
  • 20,117
  • 14
  • 67
  • 113