2013-09-17 1 views
10

У меня есть список следующим образом:Как удалить элемент из списка в Scala, имеющий только свой индекс?

val internalIdList: List[Int] = List() 

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

Из этого списка будет удалить третий элемент для того, чтобы получить:

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

Я не могу использовать ListBuffer, обязаны сохранить существующую структуру , Как я могу это сделать?

Спасибо всем

ответ

13

Если вы знаете, что будет падать третий элемент (индекс 2), то вы можете просто использовать

val trunced = internalIdList.take(2) ++ internalIdList.drop(3) 

в противном случае, если вы не знаете заранее, что индекс будет элемент для удаления, вы могли бы написать функцию, как следующее:

def removeIndex(ix: Int) = if (internalIdList.size < ix) internalIdList 
          else internalIdList.take(ix) ++ internalIdList.drop(ix+1) 
+0

КРП/другое бесполезно: взять и падение будет вести себя, как ожидается, если данный показатель больше, чем размер. – Nicolas

+0

Qool - не думал проверять это. – Shadowlands

9

Идиоматического способ сделать это, чтобы пронестись значением их индекс, фильтр, а затем снова проецировать значение:

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

Но вы также можете использовать 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) 
0
(internalIdList.indices.collect { case i if i != 3 => internalList(i) }).toList 

Чтобы обобщить это ...

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

Хотя это часто возвращают вектор, так что вам нужно будет сделать

val otherList = removeIndex(internalIdList, 3).toList 

Если вам действительно нужен список.

У Shadowlands есть решение, которое имеет тенденцию к ускорению линейных последовательностей для. Это будет быстрее с индексированными последовательностями.

0

Обобщенная функция, которая реализует первое решение Николаса:

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

Использование:

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) 
29

Существует .patch метод на Seq, поэтому для того, чтобы удалить третий элемент, который вы могли бы просто сделать это:

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

Третий параметр (1) означает удалить только один элемент.

Знание этого метода в глубине позволяет сделать это намного больше. Вы можете поменять любой подсписок списка с произвольным.

1

Если вы настаиваете на использовании OLDSCHOOL метода, использование сбора:

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

Однако, я до сих пор предпочитаю метод в моей другой ответ.

0

Использование для понимания в списке xs как это,

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

Также рассмотреть набор индексов исключения, например val excl = Set(2,4) за исключением второго и четвертого пунктов; следовательно, мы собираем те пункты, индексы не принадлежат множеству исключений, а именно

for (i <- 0 until xs.size if !excl(i)) yield xs(i)