ผนวกองค์ประกอบท้ายของรายการใน Scala


223

ดูเหมือนคำถามงี่เง่า แต่สิ่งที่ฉันพบบนอินเทอร์เน็ตคือถังขยะ ฉันไม่สามารถเพิ่มองค์ประกอบประเภทTลงในรายการList[T]ได้ ฉันลองด้วยmyList ::= myElementแต่ดูเหมือนว่ามันจะสร้างวัตถุแปลก ๆ และเข้าถึงเพื่อmyList.lastคืนองค์ประกอบแรกที่อยู่ในรายการเสมอ

คำตอบ:


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

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

โปรดทราบว่าการดำเนินการนี้มีความซับซ้อนของ O (n) หากคุณต้องการการดำเนินการนี้บ่อยครั้งหรือสำหรับรายการที่มีขนาดยาวลองใช้ชนิดข้อมูลอื่น (เช่น ListBuffer)


7
ไม่มี O (2 * n), ปัจจัยคงที่จะถูกละเว้นสำหรับความซับซ้อนเชิงซ้อน ฉันคิดว่าListมันถูกแปลงเป็น a ListBuffer, องค์ประกอบถูกผนวกเข้าด้วย, และการListBufferแปลงกลับ (เหมือนStringและStringBuilderใน Java), แต่นั่นเป็นเพียงการคาดเดา
Landei

2
มันเป็น O (n) เพราะคุณต้องสำรวจรายการทั้งหมดเพื่อไปให้ถึงตัวชี้องค์ประกอบสุดท้ายและสามารถผนวกองค์ประกอบที่ทำให้ตัวชี้องค์ประกอบสุดท้ายชี้ไปที่มัน
pisaruk

39
@pisaruk หากเป็นเช่นนั้นเราสามารถรักษาตัวชี้ไปที่หัวและหางได้ อย่างไรก็ตามรายการในสกาล่านั้นไม่สามารถเปลี่ยนแปลงได้ซึ่งหมายความว่า "แก้ไข" องค์ประกอบสุดท้ายของรายการหนึ่งต้องทำสำเนาก่อน สำเนาของมันคือ O (n) - ไม่ใช่การข้ามผ่านของรายการ

2
ฉันเชื่อว่ามันเป็น O (n) เพียงเพราะสร้างรายการใหม่
Raffaele Rossi

3
ตัวดำเนินการ cons มีความซับซ้อน O (1) เนื่องจากทำงานบนด้าน "ตั้งใจ" ของรายการ
Landei

67

นั่นเป็นเพราะคุณไม่ควรทำ (อย่างน้อยกับรายการที่ไม่เปลี่ยนรูป) ถ้าคุณต้องการผนวกองค์ประกอบไปยังจุดสิ้นสุดของโครงสร้างข้อมูลจริง ๆ และโครงสร้างข้อมูลนี้จำเป็นต้องมีรายการจริงๆและรายการนี้จะต้องไม่เปลี่ยนรูปแล้วทำสิ่งนี้:

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

หรือว่า:

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

ขอบคุณมาก! นั่นคือสิ่งที่ฉันกำลังค้นหา ฉันเดาจากคำตอบของคุณฉันไม่ควรทำอย่างนั้น ... ฉันจะแก้ไขโครงสร้างและดูว่าฉันจะทำอะไรได้บ้าง ขอบคุณอีกครั้ง.
Masiar

6
@Masiar ใช้ Vector หากคุณต้องการผนวกและผนวกอย่างมีประสิทธิภาพ ดูส่วนลักษณะการทำงานในscala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl

29
"สร้างรายการโดยการเติมแล้วย้อนกลับ" เป็นรูปแบบที่มีประโยชน์หากคุณมีองค์ประกอบหลายอย่างที่จะเพิ่ม แต่ฉันไม่คิดว่ามันเป็นความคิดที่ดีที่จะใช้มันเหมือนกับที่คุณทำในกรณีของการเพิ่มองค์ประกอบเดียวลงใน รายการที่มีอยู่ เคล็ดลับ "double reverse" สร้างรายการขึ้นใหม่สองครั้งในขณะที่:+ไม่มีประสิทธิภาพเท่าที่ควรจะสามารถสร้างได้เพียงครั้งเดียวเท่านั้น
Nicolas Payette

25

รายการใน Scala ไม่ได้ถูกออกแบบมาให้แก้ไข ในความเป็นจริงคุณไม่สามารถเพิ่มองค์ประกอบกับสกาล่าList; มันเป็นโครงสร้างข้อมูลที่เปลี่ยนแปลงไม่ได้เช่น Java String สิ่งที่คุณทำจริงเมื่อคุณ "เพิ่มองค์ประกอบในรายการ" ใน Scala คือการสร้างรายการใหม่จากรายการที่มีอยู่ (ที่มา)

แทนการใช้รายการสำหรับกรณีการใช้งานดังกล่าวผมขอแนะนำให้ใช้อย่างใดอย่างหนึ่งหรือArrayBuffer ListBufferโครงสร้างข้อมูลเหล่านั้นออกแบบมาเพื่อเพิ่มองค์ประกอบใหม่

ในที่สุดหลังจากการดำเนินการทั้งหมดของคุณเสร็จสิ้นแล้วบัฟเฟอร์สามารถถูกแปลงเป็นรายการ ดูตัวอย่าง 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)

3

นี่คล้ายกับหนึ่งในคำตอบ แต่ต่างกัน:

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

เราสามารถผนวกหรือเติมสองรายการหรือรายการ & อาร์เรย์
ผนวก:

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

prepending:

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

Result:6 5 4 1 2 3

1
ใช่เราทำได้ แต่มันจะเป็นความคิดที่ไม่ดีด้วยเหตุผลทั้งหมดที่กล่าวถึงในคำตอบอื่น ๆ
jwvh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.