2009-09-18 46 views
12

Tôi muốn sao chép một danh sách ở Scala.Cách sao chép danh sách trong Scala

tôi muốn làm somehing như:

val myList = List("foo", "bar") 
val myListCopy = myList.clone 

Nhưng phương pháp nhân bản được bảo vệ.

+0

Điều đó có liên quan đến http://stackoverflow.com/questions/1267261/does-scala-anyref-clone-perform-a-shallow-or-deep-copy không? – VonC

+12

Để làm gì? Liệt kê các đối tượng là không thay đổi. –

+1

Tôi muốn xóa một phần tử khỏi danh sách (sử dụng phương thức remove (A => Boolean)) trong một vòng lặp. (Lưu ý: Tôi đã bắt đầu Scala 2 giờ trước :)) – Maxime

Trả lời

6

Để lọc một danh sách:

val list = List(1,2,3,4,5) 
//only evens 
val evens = list.filter(e=>e%2 == 0) 

println(list) 
//--> List(1, 2, 3, 4, 5) 

println(evens) 
//--> List(2, 4) 

Bạn cũng có thể sử dụng các ký tự đại diện để tiết kiệm một vài nhân vật:

val evens = list.filter(_%2==0) 

Lưu ý rằng, như nhận xét ở trên, danh sách là không thay đổi. Điều đó có nghĩa rằng các hoạt động này không sửa đổi danh sách gốc, nhưng thực sự tạo một danh sách mới.

13

Đây là câu trả lời: không làm điều đó. Một List là không thay đổi, do đó, hoàn toàn không có điểm trong việc sao chép một.

Hãy xem xét một vài hoạt động:

val list = List(1,2,3) 
val l1 = 0 :: list 
val l2 = "a" :: list 

Cả l1 cũng không l2 là thay đổi list, nhưng cả hai đều tạo danh sách mới mà tham khảo list.

Hãy giải thích chi tiết điều này. Hàm tạo List(1,2,3) đang tạo ba phần tử và sử dụng một đối tượng đơn lẻ. Cụ thể, nó đang khởi tạo các yếu tố này:

::(3, Nil) 
::(2, reference to the previous element) 
::(1, reference to the previous element) 

Nil là một đối tượng đơn lẻ. Mã định danh list thực sự trỏ đến là phần tử cuối cùng.

Bây giờ, khi bạn gán 0 :: list-l1, bạn đang instantiating một đối tượng mới:

::(0, reference to ::(1, etc)) 

Tất nhiên, kể từ khi có một tham chiếu đến list, bạn có thể nghĩ l1 như một danh sách bốn yếu tố (hoặc năm, nếu bạn đếm Nil).

Bây giờ l2 thậm chí không cùng loại list, nhưng C ALNG cũng tham khảo nó! Tại đây:

::("a", reference to ::(1, etc)) 

Điểm quan trọng nhất về tất cả các đối tượng này là chúng không thể thay đổi. Không có người định cư, cũng không phải bất kỳ phương pháp nào sẽ thay đổi bất kỳ thuộc tính nào của họ. Họ sẽ mãi mãi có cùng giá trị/tham chiếu trong "đầu" của họ (đó là cái mà chúng ta gọi là phần tử đầu tiên) và cùng tham chiếu trong "đuôi" của chúng (đó là thứ chúng ta gọi là phần tử thứ hai).

Tuy nhiên, có các phương pháp mà xem giống như việc chúng đang thay đổi danh sách. Tuy nhiên, hãy yên tâm rằng họ đang tạo các danh sách mới mới.Ví dụ:

val l3 = list map (n => n + 1) 

Bản đồ phương pháp tạo ra một danh sách hoàn toàn mới, có cùng kích thước, nơi yếu tố mới có thể được tính toán từ một yếu tố tương ứng trong list (nhưng bạn có thể bỏ qua các yếu tố cũ cũng).

val l4 = l2 filter (n => n.isInstanceOf[Int]) 

Trong khi l4 có các yếu tố tương tự như list (nhưng một loại khác nhau), nó cũng là một danh sách hoàn toàn mới. Phương thức filter tạo danh sách mới, dựa trên quy tắc bạn vượt qua để cho biết yếu tố nào đi vào và điều gì không. Nó không cố gắng tối ưu hóa trong trường hợp nó có thể trả về một danh sách hiện có.

val l5 = list.tail 

Điều này không tạo danh sách mới. Thay vào đó, nó chỉ đơn giản gán cho l5 một phần tử hiện có của list.

val l6 = list drop 2 

Một lần nữa, không tạo danh sách mới.

val l7 = list take 1 

này, tuy nhiên, tạo ra một danh sách mới, chính vì nó không thể thay đổi các yếu tố đầu tiên của list sao cho các điểm đuôi của nó để Nil.

Dưới đây là một vài chi tiết thực hiện thêm:

  • List là một lớp trừu tượng. Nó có hai con cháu, lớp :: (có, đó là tên của lớp), và đối tượng đơn lẻ Nil. List được niêm phong, vì vậy bạn không thể thêm các lớp con mới vào nó, và :: là cuối cùng, vì vậy bạn không thể phân lớp nó.

  • Mặc dù bạn không thể làm bất cứ điều gì để thay đổi danh sách, nó sử dụng trạng thái có thể thay đổi nội bộ trong một số hoạt động. Điều này giúp với hiệu suất, nhưng nó được bản địa hóa để không chương trình nào bạn viết có thể phát hiện ra nó, hoặc chịu hậu quả từ nó. Bạn có thể chuyển danh sách xung quanh như bạn muốn, bất kể các chức năng khác làm gì với chúng, hoặc có bao nhiêu luồng đang sử dụng chúng đồng thời.

Các vấn đề liên quan