Anexando um elemento ao final de uma lista no Scala

223

Parece uma pergunta estúpida, mas tudo que encontrei na internet foi lixo. Simplesmente não consigo adicionar um elemento do tipo Tem uma lista List[T]. Eu tentei com, myList ::= myElementmas parece que cria um objeto estranho e acessar amyList.last sempre retorna o primeiro elemento que foi colocado dentro da lista.

Masiar
fonte

Respostas:

394
List(1,2,3) :+ 4

Results in List[Int] = List(1, 2, 3, 4)

Observe que esta operação possui uma complexidade de O (n). Se você precisar desta operação com freqüência ou para listas longas, considere usar outro tipo de dados (por exemplo, um ListBuffer).

Landei
fonte
7
Não há O (2 * n), fatores constantes são ignorados para complexidades assintóticas. Eu acho que o Listé convertido em um ListBuffer, o elemento é anexado, ea ListBuffervolta convertido (muito bem como Stringe StringBuilderem Java), mas isso é apenas um palpite.
Landei 9/08/2013
2
É O (n) porque você precisa percorrer a lista inteiramente para alcançar o último ponteiro do elemento e poder anexar o elemento que faz o último ponteiro do elemento apontar para ele.
pisaruk 13/09/13
39
@pisaruk, se esse fosse o caso, seria possível manter um ponteiro na cabeça e na cauda. No entanto, a lista no scala é imutável, o que significa que, para "modificar" o último elemento da lista, é necessário fazer uma cópia dele primeiro. É a cópia que é O (n) - não a travessia da própria lista.
2
Eu acredito que é O (n), simplesmente porque cria uma marca nova lista
Raffaele Rossi
3
O operador contras tem complexidade O (1), pois funciona no lado "pretendido" da lista.
Landei
67

Isso porque você não deve fazer isso (pelo menos com uma lista imutável). Se você realmente precisa acrescentar um elemento ao final de uma estrutura de dados e essa estrutura de dados realmente precisa ser uma lista e essa lista realmente precisa ser imutável, faça o seguinte:

(4 :: List(1,2,3).reverse).reverse

ou aquilo:

List(1,2,3) ::: List(4)
agilesteel
fonte
Muito obrigado! Era exatamente o que eu estava procurando. Acho que pela sua resposta eu não deveria fazer isso ... Vou revisar minha estrutura e ver o que posso fazer. Obrigado novamente.
Masiar
6
@Masiar use um Vector se quiser imutabilidade e anexos eficientes. Veja a seção de características de desempenho em scala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl
29
O "construir a lista anexando e depois revertendo" é um padrão útil se você tiver muitos elementos a serem adicionados, mas não acho que seja uma boa idéia aplicá-la como no caso de adicionar um único elemento a um elemento. lista existente. O truque "reverso duplo" reconstrói a lista duas vezes, enquanto :+, por mais ineficiente que seja, apenas a reconstrói uma vez.
Nicolas Payette
25

As listas no Scala não foram projetadas para serem modificadas. De fato, você não pode adicionar elementos a um Scala List; é uma estrutura de dados imutável , como uma Java String. O que você realmente faz quando "adiciona um elemento a uma lista" no Scala é criar uma nova lista a partir de uma lista existente . (Fonte)

Em vez de usar listas para esses casos de uso, sugiro usar um ArrayBufferou a ListBuffer. Essas estruturas de dados são projetadas para adicionar novos elementos.

Finalmente, depois que todas as suas operações estiverem concluídas, o buffer poderá ser convertido em uma lista. Veja o seguinte exemplo REPL:

scala> import scala.collection.mutable.ListBuffer
import scala.collection.mutable.ListBuffer

scala> var fruits = new ListBuffer[String]()
fruits: scala.collection.mutable.ListBuffer[String] = ListBuffer()

scala> fruits += "Apple"
res0: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple)

scala> fruits += "Banana"
res1: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple, Banana)

scala> fruits += "Orange"
res2: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple, Banana, Orange)

scala> val fruitsList = fruits.toList
fruitsList: List[String] = List(Apple, Banana, Orange)
Markus Weninger
fonte
3

Isso é semelhante a uma das respostas, mas de maneira diferente:

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

scala> val y=x:::4::Nil
y: List[Int] = List(1, 2, 3, 4)
Venkat
fonte
2

Podemos acrescentar ou acrescentar duas listas ou list & array
Anexar:

var l = List(1,2,3)    
l=l:+4 
Result : 1 2 3 4  
var ar = Array(4,5,6)    
for(x<-ar)    
{ l=l:+x}  
  l.foreach(println)

Result:1 2 3 4 5 6

Anexar:

var l = List[Int]()  
   for(x<-ar)  
    { l=x::l } //prepending    
     l.foreach(println)   

Result:6 5 4 1 2 3
Ramesh Muthavarapu
fonte
1
Sim, podemos, mas seria uma má ideia por todos os motivos mencionados nas outras respostas.
jwvh