Scala: วิธีที่ดีที่สุดในการผนวกองค์ประกอบเข้ากับ Array คืออะไร?


111

บอกว่าฉันArray[Int]ชอบ

val array = Array( 1, 2, 3 )

ตอนนี้ฉันต้องการต่อท้ายองค์ประกอบในอาร์เรย์พูดค่า4ดังในตัวอย่างต่อไปนี้:

val array2 = array + 4     // will not compile

แน่นอนฉันสามารถใช้System.arraycopy()และทำสิ่งนี้ได้ด้วยตัวเอง แต่ต้องมีฟังก์ชั่นไลบรารี Scala สำหรับสิ่งนี้ซึ่งฉันหาไม่พบ ขอบคุณสำหรับคำแนะนำ!

หมายเหตุ:

  1. ฉันทราบว่าฉันสามารถต่อท้าย Array ขององค์ประกอบอื่นได้เช่นในบรรทัดต่อไปนี้ แต่ดูเหมือนจะกลมเกินไป:

    val array2b = array ++ Array( 4 )     // this works
  2. ฉันตระหนักถึงข้อดีและข้อเสียของ List vs Array และที่นี่ฉันมีเหตุผลหลายประการที่สนใจในการขยาย Array โดยเฉพาะ

แก้ไข 1

ขอบคุณสำหรับคำตอบที่ชี้ไปที่:+วิธีการดำเนินการ นี่คือสิ่งที่ฉันกำลังมองหา น่าเสียดายที่มันค่อนข้างช้ากว่าการใช้งานเมธอด append () ที่กำหนดเองโดยใช้arraycopy- ช้ากว่าประมาณสองถึงสามเท่า เมื่อมองไปที่การนำไปใช้งานSeqLike[]ตัวสร้างจะถูกสร้างขึ้นจากนั้นอาร์เรย์จะถูกเพิ่มเข้าไปจากนั้นการผนวกจะดำเนินการผ่านตัวสร้างจากนั้นตัวสร้างจะแสดงผล ไม่ใช่การนำไปใช้งานที่ดีสำหรับอาร์เรย์ ฉันทำการเปรียบเทียบอย่างรวดเร็วโดยเปรียบเทียบทั้งสองวิธีโดยดูเวลาที่เร็วที่สุดจากสิบรอบ การทำซ้ำ 10 ล้านครั้งของรายการเดียวต่อท้ายอินสแตนซ์อาร์เรย์ 8 องค์ประกอบของบางคลาสFooใช้เวลา 3.1 วินาที:+และ 1.7 วินาทีด้วยappend()วิธีการง่ายๆที่ใช้System.arraycopy();การทำซ้ำ 10 ล้านรายการต่อท้ายบนอาร์เรย์ 8 องค์ประกอบของ Long ใช้เวลา 2.1 วินาที:+และ 0.78 วินาทีด้วยappend()วิธีง่ายๆ สงสัยว่าสิ่งนี้ไม่สามารถแก้ไขได้ในไลบรารีด้วยการใช้งานแบบกำหนดเองสำหรับArray?

แก้ไข 2

สำหรับสิ่งที่คุ้มค่าฉันยื่นตั๋ว: https://issues.scala-lang.org/browse/SI-5017


11
ทำไมไม่ใช้ArrayBufferและ+=วิธีการ? ที่จะให้คุณตัดจำหน่าย O (1) ต่อท้าย
Fred Foo

1
ใน scala System.arraycopy(...)ถูกแทนที่ด้วยArray.copy(...)
paradigmatic

1
คุณตระหนักถึงข้อดีและข้อเสียของ List vs Array แต่รู้สึกประหลาดใจกับผลลัพธ์มาตรฐาน 10 ล้านต่อท้ายหรือไม่?
ไม่ทราบผู้ใช้

คุณสามารถเรียกใช้เกณฑ์มาตรฐานของคุณอีกครั้งโดยใช้สิ่งArrayBufferที่แปลงหลังจากผนวกสุดท้ายกับอาร์เรย์ (ด้วยtoArray) ได้หรือไม่?
paradigmatic

@paradigmatic: แน่นอนว่าเกณฑ์มาตรฐานไม่ใช่ 10 ล้านต่อท้ายอาร์เรย์เดียวกัน แต่มีการซ้ำ 10 ล้านรายการของรายการเดียวต่อท้ายอาร์เรย์ 8 องค์ประกอบ ฉันอัปเดตคำถามตามนั้น
Gregor Scheidt

คำตอบ:


204

คุณสามารถใช้:+เพื่อต่อท้ายองค์ประกอบกับอาร์เรย์และ+:นำหน้ามัน:

0 +: array :+ 4

ควรผลิต:

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

มันเป็นเช่นเดียวกับการดำเนินการอื่น Seq


3
มันเหมือนกันสำหรับคอลเลกชันอื่น ๆ ที่สั่งซื้อสกาลาซึ่งใช้ไม่ได้กับชุดตัวอย่างเช่น (เนื่องจากคำนำหน้าและต่อท้ายไม่มีความหมายอะไรสำหรับชุด)
Nicolas

@Nicolas ลำดับใดก็ได้ สั่งซื้อนัยเรียง
Daniel C. Sobral

@ แดเนียลใช่ฉันมีช่องความทรงจำเล็ก ๆ เมื่อฉันเขียนความคิดเห็นและฉันไม่พบคำว่า "ลำดับ" ที่ชัดเจน
นิโคลัส

@tenshi ตัวดำเนินการทั้งหมดนี้จะสร้างอาร์เรย์ใหม่หรือไม่? ใช่ (จาก: + รหัส)Array.copy(repr, 0, result, 0, repr.length)
Timofey

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

ยังทำงาน "ย้อนกลับ":

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

นอกจากนี้ยังมีเวอร์ชัน "แทนที่":

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

11
ฉันแค่สงสัยว่าทำไม Array collection ไม่ใช้วิธี append () เหมือนกับ ArrayBuffer ในความคิดของฉันมันเป็นการประสานงานและรวมกันมากกว่าการใช้ตัวดำเนินการใหม่: + / +:
Djvu

8

วิธีที่ง่ายที่สุดอาจเป็น:

Array(1, 2, 3) :+ 4

ที่จริงแล้ว Array สามารถแปลงเป็นไฟล์ WrappedArray


ในกรณีนั้นนั่นจะเป็นการแปลงลำดับความสำคัญสูงกว่าไปยัง ArrayOps
Didier Dupont
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.