Mảng. Thêm vs = =


178

Tôi đã tìm thấy một số hành vi thú vị trong Mảng PowerShell, cụ thể là, nếu tôi khai báo một mảng là:

$array = @()

Và sau đó thử thêm các mục vào nó bằng $array.Add("item")phương thức, tôi nhận được lỗi sau:

Ngoại lệ gọi "Thêm" với (1) đối số: "Bộ sưu tập có kích thước cố định."

Tuy nhiên, nếu tôi chắp thêm các mục bằng cách sử dụng $array += "item", mục đó được chấp nhận mà không có vấn đề gì và hạn chế "kích thước cố định" dường như không áp dụng.

Tại sao lại thế này?

Câu trả lời:


253

Khi sử dụng $array.Add()-method, bạn đang cố gắng thêm phần tử vào mảng hiện có. Mảng là một tập hợp các kích thước cố định, vì vậy bạn sẽ nhận được một lỗi vì nó không thể được mở rộng.

$array += $elementtạo một mảng mới với các phần tử giống như phần tử cũ + mục mới và mảng mới lớn hơn này thay thế mảng cũ trong phần có thể $arraythay đổi

Bạn có thể sử dụng toán tử + = để thêm một phần tử vào một mảng. Khi bạn sử dụng nó, Windows PowerShell thực sự tạo ra một mảng mới với các giá trị của mảng ban đầu và giá trị gia tăng. Ví dụ: để thêm một phần tử có giá trị 200 vào mảng trong biến $ a, hãy gõ:

    $a += 200

Nguồn: about_Arays

+= là một hoạt động đắt tiền, vì vậy khi bạn cần thêm nhiều mục, bạn nên cố gắng thêm chúng vào càng ít thao tác càng tốt, ví dụ:

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

$arr.Count
5

Nếu đó là không thể, xem xét sử dụng một bộ sưu tập hiệu quả hơn như Listhay ArrayList(xem câu trả lời khác).


Cảm ơn :) Nghĩ rằng nó có thể là một cái gì đó như thế này nhưng nghĩ rằng nó sẽ không hiệu quả với các mảng lớn, vì vậy nhóm powershell đang làm một cái gì đó khác nhau.
malgca

6
điều đó hoàn toàn chính xác, nó trở nên không hiệu quả với các mảng lớn, thật không may để giải quyết vấn đề này, bạn phải sử dụng một loại khác: powershell.org/wp/2013/09/16/ trên
Nacht

3
Nó phụ thuộc. Nếu bạn sẽ thêm và loại bỏ rất nhiều thành viên thì có, hãy thử Listhoặc ArrayList. Họ sẽ nhanh hơn nhiều. Cá nhân tôi sử dụng +=và sắp xếp 99% thời gian vì tôi thường tạo ra các kịch bản ném đi ngắn trong đó các giây thêm không thành vấn đề. Đối với các tập lệnh lớn có nhiều add / remove nơi tôi muốn tối ưu hóa và tiết kiệm thời gian tôi sử dụng Listhoặc ArrayList.
Frode F.

3
Vì các mảng luôn có kích thước cố định, có ai biết tại sao Add()phương thức này tồn tại không?
JohnLBevan

4
Bởi vì nó được thừa hưởng từ IList. Thử Get-Member -InputObject @()sẽ cho thấy điều nàyAdd Method int IList.Add(System.Object value)
Frode F.

113

Nếu bạn muốn một mảng có kích thước động, thì bạn nên lập một danh sách. Bạn không chỉ nhận được.Add() chức năng, mà như @ frode-f giải thích, mảng động còn hiệu quả hơn về bộ nhớ và dù sao cũng là một cách thực hành tốt hơn.

Và nó rất dễ sử dụng.

Thay vì khai báo mảng của bạn, hãy thử điều này:

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

Thêm các mục là đơn giản.

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

Và nếu bạn thực sự muốn một mảng khi bạn hoàn thành, thì cũng có một chức năng cho điều đó.

$outItems.ToArray()

1
Tôi đã thử điều này. Tôi tạo nó bằng New-Object System.Collections.Generic.List [string] nhưng sau đó nếu tôi làm .GetType, nó sẽ cho tôi biết đó là một mảng.
Preza8

1
Bạn đã thử sử dụng Add()chức năng? Tôi có thể xác nhận, nếu bạn tạo một Listđối tượng chung như đã nêu ở trên, bạn có một danh sách có thể thay đổi để bạn có thể thêm và xóa các mục bằng cách sử dụng các phương thức Add()Remove()phương thức tương ứng.
Bender lớn nhất

1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Namesản lượng List`1cho tôi, như mong đợi; có lẽ bạn đã áp dụng +=cho biến chứa danh sách (thay vì gọi .Add()phương thức), trong trường hợp đó, giá trị biến thực sự sẽ được chuyển đổi thành một mảng ( System.Object[]).
mkuity0

Phím tắt:$a = new-object collections.generic.list[object]
Andrew

4

Thành ngữ phổ biến nhất để tạo một mảng mà không sử dụng không hiệu quả +=là một cái gì đó như thế này, từ đầu ra của một vòng lặp:

$array = foreach($i in 1..10) { 
  $i
}
$array
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.