Array.Add vs + =


179

ฉันพบพฤติกรรมที่น่าสนใจใน PowerShell Arrays คือถ้าฉันประกาศอาร์เรย์เป็น:

$array = @()

จากนั้นลองเพิ่มรายการโดยใช้$array.Add("item")วิธีการฉันได้รับข้อผิดพลาดต่อไปนี้:

ข้อยกเว้นการเรียก "เพิ่ม" ด้วยอาร์กิวเมนต์ "1": "การรวบรวมมีขนาดคงที่"

อย่างไรก็ตามหากฉันต่อท้ายรายการโดยใช้$array += "item"รายการนั้นจะได้รับการยอมรับโดยไม่มีปัญหาและข้อ จำกัด "ขนาดคงที่" จะไม่ปรากฏ

ทำไมนี้

คำตอบ:


254

เมื่อใช้$array.Add()-method คุณกำลังพยายามเพิ่มองค์ประกอบลงในอาร์เรย์ที่มีอยู่ อาร์เรย์คือชุดของขนาดคงที่ดังนั้นคุณจะได้รับข้อผิดพลาดเนื่องจากไม่สามารถขยายได้

$array += $elementสร้างอาร์เรย์ใหม่ที่มีองค์ประกอบเดียวกับรายการเก่าและรายการใหม่และอาร์เรย์ขนาดใหญ่ใหม่นี้จะแทนที่อาร์เรย์เก่าใน$array-variable

คุณสามารถใช้ตัวดำเนินการ + = เพื่อเพิ่มองค์ประกอบลงในอาร์เรย์ เมื่อคุณใช้ Windows PowerShell จะสร้างอาร์เรย์ใหม่ด้วยค่าของอาร์เรย์ดั้งเดิมและมูลค่าเพิ่ม ตัวอย่างเช่นในการเพิ่มองค์ประกอบที่มีค่า 200 ไปยังอาร์เรย์ในตัวแปร $ a ให้พิมพ์:

    $a += 200

ที่มา: about_Arrays

+= เป็นการดำเนินการที่มีราคาแพงดังนั้นเมื่อคุณต้องการเพิ่มหลายรายการคุณควรลองเพิ่มเข้าไปในการดำเนินการให้น้อยที่สุดเช่น:

$arr = 1..3    #Array
$arr += (4..5) #Combine with another array in a single write-operation

$arr.Count
5

หากไม่สามารถทำได้ให้ลองใช้คอลเล็กชันที่มีประสิทธิภาพมากกว่าเช่นListหรือArrayList(ดูคำตอบอื่น ๆ )


ขอบคุณ :) คิดว่ามันอาจเป็นแบบนี้ แต่คิดว่ามันจะไม่มีประสิทธิภาพกับอาร์เรย์ขนาดใหญ่ดังนั้นทีมงานของ powershell จึงทำสิ่งที่แตกต่างออกไป
malgca

6
ถูกต้องแล้วมันจะไม่มีประสิทธิภาพกับอาร์เรย์ขนาดใหญ่โชคไม่ดีที่ได้รับสิ่งนี้คุณต้องใช้ประเภทอื่น: powershell.org/wp/2013/09/16/…
Nacht

3
มันขึ้นอยู่กับ. หากคุณกำลังจะไปเพิ่มและลบจำนวนมากของสมาชิกแล้วใช่ลองหรือList ArrayListพวกเขาจะเร็วขึ้นมาก ฉันใช้งานเอง+=และจัดลำดับ 99% ของเวลาเพราะฉันมักจะสร้างสคริปต์สั้น ๆ ซึ่งไม่กี่วินาทีพิเศษ สำหรับสคริปต์ขนาดใหญ่ที่มีจำนวนมากเพิ่ม / ลบที่ฉันต้องการที่จะเพิ่มประสิทธิภาพและประหยัดการใช้เวลาฉันหรือList ArrayList
Frode F.

3
ในฐานะที่เป็นอาร์เรย์ที่มีขนาดคงที่เสมอไม่มีใครรู้ว่าทำไมAdd()วิธีการที่มีอยู่?
JohnLBevan

4
IListเพราะมันสืบทอดมาจาก ลองGet-Member -InputObject @()จะแสดงสิ่งนี้Add Method int IList.Add(System.Object value)
Frode F.

113

ถ้าคุณต้องการอาร์เรย์ที่มีขนาดแบบไดนามิกคุณควรสร้างรายการ ไม่เพียง แต่คุณจะได้รับ.Add()ฟังก์ชั่นการใช้งานเท่านั้น แต่ตามที่ @ frode-f อธิบายว่าอาร์เรย์แบบไดนามิกนั้นมีหน่วยความจำที่มีประสิทธิภาพมากกว่าและมีวิธีปฏิบัติที่ดีกว่าอยู่ดี

และมันใช้งานง่ายมาก

แทนการประกาศอาร์เรย์ของคุณลองสิ่งนี้:

$outItems = New-Object System.Collections.Generic.List[System.Object]

การเพิ่มรายการเป็นเรื่องง่าย

$outItems.Add(1)
$outItems.Add("hi")

และถ้าคุณต้องการอาเรย์เมื่อเสร็จแล้วก็มีฟังก์ชั่นสำหรับมันเช่นกัน

$outItems.ToArray()

1
ฉันได้ลองสิ่งนี้แล้ว ฉันสร้างมันโดยใช้ New-Object System.Collections.Generic.List [string] แต่ถ้าฉันทำ. GetType มันบอกฉันว่ามันเป็นอาร์เรย์
Preza8

1
คุณลองใช้Add()ฟังก์ชั่นนี้หรือไม่? ฉันสามารถยืนยันได้หากคุณสร้างListวัตถุทั่วไปตามที่ระบุไว้ข้างต้นคุณมีรายการที่ไม่แน่นอนซึ่งคุณสามารถเพิ่มและลบรายการโดยใช้Add()และRemove()วิธีการตามลำดับ
Bender the Greatest

1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Nameให้ผลตอบแทนList`1ตามที่คาดไว้ บางทีคุณอาจนำไปใช้+=กับตัวแปรที่มีรายการ (แทนที่จะเรียก.Add()วิธีการ) ซึ่งในกรณีนี้ค่าตัวแปรจะถูกแปลงเป็นอาร์เรย์ ( System.Object[])
mklement0

ทางลัด:$a = new-object collections.generic.list[object]
Andrew

4

สำนวนที่พบมากที่สุดสำหรับการสร้างอาร์เรย์โดยไม่ต้องใช้ไม่มีประสิทธิภาพ+=คืออะไรเช่นนี้จากการส่งออกของวง:

$array = foreach($i in 1..10) { 
  $i
}
$array
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.