Dizi. + + =


179

Ben bir dizi olarak ilan eğer, yani, PowerShell Diziler bazı ilginç davranış buldum:

$array = @()

Ve sonra $array.Add("item")yöntemi kullanarak öğeyi eklemeyi deneyin , aşağıdaki hatayı alıyorum:

"1" argümanıyla "Ekle" çağrısı yapan kural dışı durum: "Koleksiyon sabit boyuttaydı."

Bununla birlikte, öğeleri kullanarak eklersem $array += "item", öğe sorunsuz kabul edilir ve "sabit boyut" kısıtlaması geçerli görünmemektedir.

Bu neden?

Yanıtlar:


254

$array.Add()-Method kullanırken, öğeyi varolan diziye eklemeye çalışıyorsunuz. Dizi sabit boyutlu bir koleksiyondur, bu nedenle genişletilemediğinden bir hata alırsınız.

$array += $elementeskisiyle + yeni öğeyle aynı öğelere sahip yeni bir dizi oluşturur ve bu yeni daha büyük dizi, $array-değişkente eski dizinin yerine geçer

Bir diziye öğe eklemek için + = operatörünü kullanabilirsiniz. Bunu kullandığınızda, Windows PowerShell aslında orijinal dizinin değerlerini ve katma değeri içeren yeni bir dizi oluşturur. Örneğin, $ a değişkenindeki diziye 200 değerine sahip bir öğe eklemek için şunu yazın:

    $a += 200

Kaynak: about_Arrays

+= pahalı bir işlemdir, bu nedenle birçok öğe eklemeniz gerektiğinde bunları mümkün olduğunca az işlemde eklemeye çalışmalısınız, örn:

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

$arr.Count
5

Bu mümkün değilse Listveya gibi daha verimli bir koleksiyon kullanmayı düşünün ArrayList(diğer cevaba bakınız).


Teşekkürler :) Bunun böyle bir şey olabileceğini düşündüm, ancak büyük dizilerle verimsiz olacağını düşündüm, bu yüzden powershell ekibi farklı bir şey yapıyorlardı.
malgca

6
bu doğru, büyük dizilerle verimsiz hale geliyor, maalesef bunun üstesinden gelmek için farklı bir tür kullanmanız gerekiyor: powershell.org/wp/2013/09/16/…
Nacht

3
Değişir. Çok sayıda üye ekleyip kaldıracaksanız, evet, Listya da deneyin ArrayList. Çok daha hızlı olacaklar. Ben şahsen kullanıyorum +=ve zamanın% 99'unu dizilim çünkü genellikle ekstra saniyelerin önemli olmadığı kısa atma komut dosyaları oluşturuyorum. Ben kullanmak Listveya zaman tasarrufu optimize etmek istiyorum eklemek / kaldırmak çok büyük komut dosyaları için veya ArrayList.
Frode F.

3
Diziler her zaman sabit bir boyutta Add()olduğundan , yöntemin neden var olduğunu bilen var mı?
JohnLBevan

4
Çünkü miras alınır IList. Bunu Get-Member -InputObject @()göstermeyi deneyinAdd Method int IList.Add(System.Object value)
Frode F.

113

Dinamik olarak boyutlandırılmış bir dizi istiyorsanız, bir liste yapmanız gerekir. Sadece .Add()işlevselliği elde etmekle kalmayacak , aynı zamanda @ frode-f'nin açıkladığı gibi dinamik diziler daha fazla bellek verimliliği ve daha iyi bir uygulama.

Ve kullanımı çok kolay.

Dizi bildiriminiz yerine şunu deneyin:

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

Öğe eklemek basittir.

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

Ve işiniz bittiğinde gerçekten bir dizi istiyorsanız, bunun için bir işlev var.

$outItems.ToArray()

1
Bunu denedim. Ben New-Object System.Collections.Generic.List [string] kullanarak oluşturun ama sonra .GetType yaparsanız, bana bir dizi olduğunu söyler.
Preza8

1
Bu Add()işlevi kullanmayı denediniz mi? ListYukarıda belirtildiği gibi genel bir nesne oluşturursanız , sırasıyla Add()ve Remove()yöntemlerini kullanarak öğe ekleyip kaldırabileceğiniz değiştirilebilir bir listeniz olduğunu onaylayabilirim .
En Büyük

1
@ Preza8: beklendiği gibi benim için (New-Object System.Collections.Generic.List[string]).GetType().Nameverim List`1; belki de +=listeyi içeren değişkeni uyguladınız ( .Add()yöntemi çağırmak yerine ), bu durumda değişken değeri gerçekten bir diziye ( System.Object[]) dönüştürülür .
mklement0

Kısayol:$a = new-object collections.generic.list[object]
Andrew

4

Verimsizliği kullanmadan bir dizi oluşturmak için en yaygın deyim +=, bir döngü çıktısından şöyle bir şeydir:

$array = foreach($i in 1..10) { 
  $i
}
$array
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.