Немного теории
Почему сейчас стоит поговорить про типизацию и классы?
Для того что бы создать изменяемый массив, нужно присвоить объект к определенному классу, содержащему необходимые методы
Powershell относят к языкам с динамической типизацией и таким образом, тип переменной определяется в момент присваивания значения, в зависимости от типа самого этого значения.
И если заранее вручную не создать экземпляр нужного класса(объект), то по умолчанию, объект которому мы присваиваем ряд значений, будет принадлежать к классу System.Array.
В свою очередь, объект System.Array не имеет возможности использовать метод add, т.к. является фиксированным массивом.
Классами, которые позволяют добавлять объекты в массив, являются:
[System.Collections.Generic.List]
или
[System.Collections.ArrayList]
Так как для класса List заявлена более высокая производительность, за счет возможности явно задать его тип данных, а ArrayList имеет те же самые методы,
то разбирать работу с массивом мы будем на примере класса List
Плюсы:
Массив имеет не фиксированный размер, что указывает на то, что в него можно добавлять, или же удалять из него элементы
Минусы:
Не сохраняется порядок объектов в массиве при выводе, в отличии от PSCustomObject
Но это не доставляет особых проблем, т.к. можно выполнить последующую сортировку, например средствами Sort-Object
Summary простыми словами:
- Объекты содержащие ряд значений называется массивом
- Массивы бывают разными
- В зависимости от класса к которому относится массив, меняется его набор свойств и методов
- Массив класса [System.Collections.Generic.List] позволяет добавлять элементы
Практическая часть
Пример создания массива
Сначала создадим экземпляр класса List
$List = New-Object 'System.Collections.Generic.List[System.Object]'
Чтобы проверить наличие у объекта нужного метода можно выполнив этот метод опустив скобки «()»
$List.add
Это вернуло нам определения перегрузок метода.
Если ничего не возвращает, то метод у объекта отсутствуют.
Что из себя представляют перегрузки методов?
Перегрузка указывают на то, как один и тот же метод, в зависимости от количества и типа данных аргументов, может выдавать отличающиеся результаты.
Определения перегрузок(OverloadDefinitions) возвращают возможные варианты перегрузок.
После того как мы убедились в наличии метода add, мы можем добавлять в массив элементы!
Добавление элементов в массив
Что бы окончательно понять как создать изменяемый массив, давайте разберем какой нибудь реальный кейс полезный для повседневной работы. Например, в рамках задачи по апгрейду устаревшего железа нам нужно провести для всех компьютеров в домене инвентаризацию объема оперативной памяти, количества занятых, и количества свободных слотов памяти.
$Computers = ( Get-ADComputer -f {Enabled -eq $true} ).Name $List = New-Object 'System.Collections.Generic.List[System.Object]' foreach($Computer in $Computers ){ if( Test-Connection $Computer -Count 1){ $RAM = ( Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer ) $TotalMemory = "{0:N0} GB"-f $( [math]::Truncate([math]::Round((Get-WmiObject Win32_ComputerSystem -ComputerName $Computer ).TotalPhysicalMemory / 1GB ))) $Count = $RAM.DeviceLocator.Count $MaxSlots = ( Get-WmiObject win32_PhysicalMemoryArray -ComputerName $Computer ).MemoryDevices $List.add( ( @{CompName=$Computer;TotalMemory=$TotalMemory;CountRAM=$Count;MaxSlots=$MaxSlots} | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }) ) } } $List | Sort-Object | select CompName,TotalMemory,CountRAM,MaxSlots
По полученному результату можно сделать заключение о необходимости и возможности апгрейда RAM
Так же можно добавить объекты в коллекцию и с помощью оператора += , но известно что данный метод более медлителен, так как в каждой итерации перезаписывает массив:
$List += [PSCustomObject]@{CompName=$Computer;TotalMemory=$TotalMemory;CountRAM=$Count;MaxSlots=$MaxSlots}
Помимо более низкой производительности, после его использования, коллекция становится фиксированной.
Поэтому лучше сразу использовать ту же конструкцию для метода add:
$List.Add( [PSCustomObject]@{Motherboard=$SysInfo;User=$user} )
Тем не менее, для простых скриптов оператор += может вполне пригодиться
Удаление элементов из массива
Есть несколько методов для удаления объектов из массива
Remove()
$List.Remove($List[3])
Для удаления нужно целиком указать объект. Проще всего это сделать указав конкретный элемент нашего массива
RemoveAt()
Так же можно удалить элемент по его порядковому номеру в массиве
$List.RemoveAt(0)
RemoveRange()
Как следует из названия, удаляет диапазон значений по их порядковым номерам
$List.RemoveRange(4,6)