Scala: cách tốt nhất để nối một phần tử vào một Mảng là gì?


111

Nói rằng tôi có một lượt Array[Int]thích

val array = Array( 1, 2, 3 )

Bây giờ tôi muốn nối một phần tử vào mảng, giả sử giá trị 4, như trong ví dụ sau:

val array2 = array + 4     // will not compile

Tất nhiên tôi có thể sử dụng System.arraycopy()và làm điều này một mình, nhưng phải có một chức năng thư viện Scala cho việc này, mà tôi chỉ đơn giản là không thể tìm thấy. Cảm ơn cho bất kỳ gợi ý!

Ghi chú:

  1. Tôi biết rằng tôi có thể nối thêm một Mảng các phần tử khác, như trong dòng sau, nhưng điều đó có vẻ quá vòng vo:

    val array2b = array ++ Array( 4 )     // this works
  2. Tôi nhận thức được những ưu điểm và nhược điểm của List vs Array và ở đây tôi vì nhiều lý do đặc biệt quan tâm đến việc mở rộng một Array.

Chỉnh sửa 1

Cảm ơn các câu trả lời chỉ đến :+phương pháp toán tử. Đây là những gì tôi đang tìm kiếm. Thật không may, nó chậm hơn so với việc triển khai phương thức append () tùy chỉnh bằng cách sử dụng arraycopy- chậm hơn khoảng hai đến ba lần. Nhìn vào việc triển khai trong SeqLike[], một trình tạo được tạo, sau đó mảng được thêm vào nó, sau đó nối thêm được thực hiện thông qua trình xây dựng, sau đó trình tạo được hiển thị. Không phải là một triển khai tốt cho các mảng. Tôi đã thực hiện một điểm chuẩn nhanh so sánh hai phương pháp, xem xét thời gian nhanh nhất trong số mười chu kỳ. Thực hiện 10 triệu lần lặp lại một mục đơn nối vào một phiên bản mảng 8 phần tử của một số lớp Foomất 3,1 giây :+và 1,7 giây với một append()phương thức đơn giản sử dụngSystem.arraycopy();thực hiện 10 triệu lần lặp lại phần nối thêm một mục trên mảng 8 phần tử của Long mất 2,1 giây :+và 0,78 giây với append()phương pháp đơn giản . Tự hỏi nếu điều này không thể được khắc phục trong thư viện với triển khai tùy chỉnh cho Array?

Chỉnh sửa 2

Vì giá trị của nó, tôi đã gửi một vé: https://issues.scala-lang.org/browse/SI-5017


11
Tại sao không sử dụng ArrayBuffer+=phương pháp của nó ? Điều đó sẽ cung cấp cho bạn phụ lục O (1) được khấu hao.
Fred Foo

1
Trong scala, System.arraycopy(...)được thay thế bằngArray.copy(...)
paradigmatic

1
Bạn nhận thức được những ưu điểm và nhược điểm của List vs Array, nhưng lại ngạc nhiên với kết quả benchmark của 10 triệu append?
người dùng không xác định

Bạn có thể chạy lại điểm chuẩn của mình bằng cách sử dụng điểm chuẩn ArrayBufferđược chuyển đổi sau lần nối cuối cùng vào một mảng (với toArray) không?
paradigmatic

@paradigmatic: Tất nhiên, điểm chuẩn không phải là 10 triệu phần nối tiếp vào cùng một mảng mà là 10 triệu lần lặp lại của một mục đơn nối vào một mảng 8 phần tử. Tôi đã cập nhật câu hỏi cho phù hợp.
Gregor Scheidt 21/09/11

Câu trả lời:


204

Bạn có thể sử dụng :+để nối phần tử vào mảng và +:thêm trước nó:

0 +: array :+ 4

nên sản xuất:

res3: Array[Int] = Array(0, 1, 2, 3, 4)

Nó giống với bất kỳ triển khai nào khác của Seq.


3
Nó cũng giống như bất kỳ bộ sưu tập có thứ tự theo tỷ lệ nào khác , nó không hoạt động với set chẳng hạn (vì prepend và append không có ý nghĩa gì đối với Set).
Nicolas

@Nicolas Trình tự bất kỳ. Có thứ tự ngụ ý được sắp xếp .
Daniel C. Sobral

@Daniel Có, tôi đã chỉ có một lỗ nhỏ bộ nhớ khi tôi viết những nhận xét và tôi không tìm thấy chữ rõ ràng "chuỗi"
Nicolas

@tenshi liệu tất cả các toán tử này có tạo ra một mảng mới không? Có, nó có (từ: + mã)Array.copy(repr, 0, result, 0, repr.length)
Timofey

59
val array2 = array :+ 4
//Array(1, 2, 3, 4)

Công việc cũng bị "đảo ngược":

val array2 = 4 +: array
Array(4, 1, 2, 3)

Ngoài ra còn có một phiên bản "tại chỗ":

var array = Array( 1, 2, 3 )
array +:= 4
//Array(4, 1, 2, 3)
array :+= 0
//Array(4, 1, 2, 3, 0)

11
Tôi chỉ thắc mắc tại sao bộ sưu tập Array không sử dụng phương thức append (), giống như ArrayBuffer. Theo tôi, nó là nhiều Phối hợp và thống nhất hơn sử dụng một nhà điều hành mới: + / +:
Djvu

8

Cách dễ nhất có thể là:

Array(1, 2, 3) :+ 4

Trên thực tế, Mảng có thể được chuyển đổi hoàn toàn trong một WrappedArray


Trong trường hợp đó, đó sẽ là sự chuyển đổi cao hơn ưu tiên ArrayOps
Didier Dupont
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.