Nối một phần tử vào cuối danh sách trong Scala


223

Nghe có vẻ như một câu hỏi ngu ngốc, nhưng tất cả những gì tôi tìm thấy trên internet là rác rưởi. Tôi chỉ đơn giản là không thể thêm một yếu tố loại Tvào danh sách List[T]. Tôi đã thử với myList ::= myElementnhưng có vẻ như nó tạo ra một đối tượng lạ và truy cập để myList.lastluôn trả về phần tử đầu tiên được đưa vào danh sách.

Câu trả lời:


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

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

Lưu ý rằng thao tác này có độ phức tạp là O (n). Nếu bạn cần thao tác này thường xuyên hoặc cho danh sách dài, hãy xem xét sử dụng loại dữ liệu khác (ví dụ: ListBuffer).


7
Không có O (2 * n), các yếu tố không đổi được bỏ qua cho các phức tạp tiệm cận. Tôi nghĩ rằng phần tử Listđược chuyển đổi thành a ListBuffer, phần tử được nối thêm và phần tử được ListBufferchuyển đổi trở lại (khá giống StringStringBuildertrong Java), nhưng đó chỉ là dự đoán.
Landei

2
Đó là O (n) vì bạn phải duyệt toàn bộ danh sách để đến con trỏ phần tử cuối cùng và có thể nối phần tử làm cho con trỏ phần tử cuối cùng trỏ vào nó.
pisaruk

39
@pisaruk nếu đó là trường hợp, người ta chỉ có thể duy trì một con trỏ đến đầu và đuôi. Tuy nhiên, danh sách trong scala là bất biến, có nghĩa là để "sửa đổi" phần tử cuối cùng của danh sách, người ta cần tạo một bản sao của nó trước. Bản sao của nó là O (n) - không phải là bản sao của danh sách.

2
Tôi tin rằng đó là O (n) đơn giản vì tạo ra một danh sách hoàn toàn mới
Raffaele Rossi

3
Toán tử khuyết có độ phức tạp O (1), vì nó hoạt động ở phía "dự định" của danh sách.
Landei

67

Đó là bởi vì bạn không nên làm điều đó (ít nhất là với một danh sách không thay đổi). Nếu bạn thực sự cần nối một phần tử vào cuối cấu trúc dữ liệu và cấu trúc dữ liệu này thực sự cần phải là một danh sách và danh sách này thực sự phải là bất biến thì hãy làm điều này:

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

hoặc rằng:

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

Cảm ơn rất nhiều! Đó chính xác là những gì tôi đang tìm kiếm. Tôi đoán từ câu trả lời của bạn Tôi không nên làm điều đó mặc dù ... Tôi sẽ sửa lại cấu trúc của mình và xem tôi có thể làm gì. Cảm ơn một lần nữa.
Masiar

6
@Masiar sử dụng Vector nếu bạn muốn bất biến và nối thêm hiệu quả. Xem phần đặc điểm hiệu suất trong scala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl

29
"Xây dựng danh sách bằng cách thêm trước và sau đó đảo ngược" là một mẫu hữu ích nếu bạn có nhiều yếu tố để thêm, nhưng tôi không nghĩ nên áp dụng nó như bạn làm trong trường hợp thêm một yếu tố vào một danh sách hiện có. Thủ thuật "đảo ngược kép" xây dựng lại danh sách hai lần, trong khi :+, không hiệu quả như nó có thể, chỉ xây dựng lại nó một lần.
Nicolas Payette

25

Danh sách trong Scala không được thiết kế để được sửa đổi. Thực tế, bạn không thể thêm các yếu tố vào Scala List; đó là một cấu trúc dữ liệu bất biến , giống như Chuỗi Java. Những gì bạn thực sự làm khi bạn "thêm một yếu tố vào danh sách" trong Scala là tạo Danh sách mới từ Danh sách hiện có . (Nguồn)

Thay vì sử dụng danh sách cho các trường hợp sử dụng như vậy, tôi đề nghị sử dụng một ArrayBufferhoặc mộtListBuffer . Những cơ sở dữ liệu được thiết kế để có các yếu tố mới được thêm vào.

Cuối cùng, sau khi tất cả các hoạt động của bạn được thực hiện, bộ đệm sau đó có thể được chuyển đổi thành một danh sách. Xem ví dụ REPL sau:

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)

3

Điều này tương tự với một trong những câu trả lời nhưng theo cách khác nhau:

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)

2

Chúng tôi có thể nối hoặc thêm hai danh sách hoặc danh sách & mảng
Nối thêm:

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

Chuẩn bị:

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

Result:6 5 4 1 2 3

1
Vâng, chúng tôi có thể, nhưng nó sẽ là một ý tưởng tồi cho tất cả các lý do được đề cập trong các câu trả lời khác.
jwvh
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.