Array.Add vs + =


179

Я знайшов цікаву поведінку в PowerShell Arrays, а саме, якщо я оголошу масив як:

$array = @()

А потім спробуйте додати до нього елементи за допомогою $array.Add("item")методу, я отримую таку помилку:

Виняток викликає "Додати" за допомогою аргументів "1": "Колекція була фіксованого розміру."

Однак якщо я додаю елементи за допомогою $array += "item", елемент приймається без проблем, і обмеження "фіксованого розміру", схоже, не застосовується.

Чому це?

Відповіді:


254

Використовуючи $array.Add()-метод, ви намагаєтеся додати елемент до існуючого масиву. Масив - це набір фіксованого розміру, тому ви отримаєте помилку, оскільки її неможливо розширити.

$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(див. Іншу відповідь).


Дякую :) Думав, що це може бути щось подібне, але думав, що це буде неефективно з великими масивами, тому команда владних команд робила щось інше.
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)
Фроде Ф.

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()методів.
Бендер найбільший

1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Nameврожайність List`1для мене, як і очікувалося; можливо, ви застосували +=до змінної, що містить список (а не виклику .Add()методу), і в цьому випадку значення змінної дійсно було б перетворено в масив ( System.Object[]).
mklement0

Ярлик:$a = new-object collections.generic.list[object]
Ендрю

4

Найпоширеніша ідіома для створення масиву без використання неефективного +=- це щось подібне, з виводу циклу:

$array = foreach($i in 1..10) { 
  $i
}
$array
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.