PowerShell — наиболее эффективный способ создания массива/списка массивов/pscustomobject

Я много читал об этом в StackOverflow, Microsoft и других источниках, но изо всех сил пытался разобраться в создании и добавлении объектов в массивы. Большинство примеров, которые я могу найти, слишком упрощены и содержат только целые числа или простые значения. Я знаю, что это не лучший способ ниже, но это просто пример того, что я пытаюсь сделать в данном случае. Мне нужно что-то, что я могу вывести в CSV, что будет иметь что-то вроде следующего, и наиболее эффективным способом (очевидно, += это плохо):

OUDN,Inheritancetype,etc  
OU=Test,Whatever  
OU=Test,Whatever  
OU=Brush,Thing  
OU=Brush,Whatever
$OUACLResults = @()
$OUs = Get-ADOrganizationalUnit -Filter *

foreach ($OU in $OUs)
{
        # additional question, I like doing it this way so I can easily use intellisense to complete the attributes like $OU.distinguishedname, is there an easy way to do this when piping?

        $OUACLs = (get-ACl ad:\$OU.Distinguishedname).access

        Foreach ($ACL in $OUACLs)
        {

              #example of other work required, this is doing a lookup in table $ObjectTypeGUID
              $ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)

              $Object = new-object -typename psobject
              Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname
              Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype
              Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType
              #and so on for other attributes

              #next line particularly inefficient
              $OUACLResults += $Object

         }

}

Судя по тому, что я видел, приведенная выше часть $object кажется эффективной (хотя передача по конвейеру и использование foreach-obj может быть лучше), но добавление $object в $OUACLResults не работает:

#tried 
$OUACLresults = @{}
$OUACLResults.add($object) 

#no overload for Add and argument count "1"

Попробуйте это: $Object = [PSCustomObject]@{ OUDN = $OU.distinguishedname; Inheritancetype = $ACL.Inheritancetype; ObjectType = $ObjectType }

Darin 14.08.2024 12:50

И воспользуйтесь этим руководством: gist.github.com/kevinblumenfeld/…

Darin 14.08.2024 12:53

В ответ на вопрос Почему мне следует избегать использования оператора присваивания увеличения (+=) для создания коллекции, я дал полное объяснение того, почему «очевидно += это плохо» и шаги, необходимые для исправления вашего сценария.

iRon 14.08.2024 13:27
+= не так ли...
js2010 14.08.2024 16:59

@iRon, я прочитал ваш ответ, но (вероятно, по моей вине) с трудом смог применить свой пример, вероятно, главным образом потому, что помещать все в конвейер казалось слишком сложным. Мне следовало упомянуть об этом в своем вопросе, поскольку ваш ответ привел меня к расследованию неэффективности +=. Спасибо :-)

Badger 15.08.2024 11:41
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
5
53
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

@{} создает хеш-таблицу — неупорядоченный словарь — вместо этого вам нужно создать список:

$OUACLResults = [System.Collections.Generic.List[psobject]]::new()

Затем в теле цикла:

$OUACLResults.Add($object)

Кроме того, использование сокращенного синтаксиса [pscustomobject]@{ ... } для создания объектов обычно происходит намного быстрее, чем New-Object + Add-Member:

$object = [pscustomobject]@{
  OUDN = $OU.distinguishedname
  Inheritancetype = $ACL.Inheritancetype
  ObjectType = $ObjectType
}

Спасибо, это привело меня туда, куда мне нужно было.

Badger 15.08.2024 11:43

это не обязательно рабочий скрипт, он приведен для примера работы с массивами. UPD https://learn.microsoft.com/ru-ru/powershell/module/microsoft.powershell.core/about/about_arrays?view=powershell-7.4#manipulated-an-array заменить +=

$OUACLResults = @()
$OUs = Get-ADOrganizationalUnit -Filter *

foreach ($OU in $OUs)
{
        # additional question, I like doing it this way so I can easily use intellisense to complete the attributes like $OU.distinguishedname, is there an easy way to do this when piping?

        $OUACLs = (get-ACl ad:\$OU.Distinguishedname).access

        Foreach ($ACL in $OUACLs)
        {
              
              #example of other work required, this is doing a lookup in table $ObjectTypeGUID
              $ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)

              #$Object = new-object -typename psobject
              $array = "" | Select OUDN, Inheritancetype, ObjectType


              #Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname
              $array.OUDN = $OU.distinguishedname

              #Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype
              $array.Inheritancetype =  $ACL.Inheritancetype

              #Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType
              $array.ObjectType = $ObjectType
              #and so on for other attributes
              write-host $array #for debug


              #next line particularly inefficient
              #$OUACLResults += $array
               $OUACLResults.add($array)
         }

}

Как описано в вопросе, += — не самая эффективная операция для добавления элементов.

lit 14.08.2024 21:08

Забавно, но это действительно Learn.microsoft.com/ru-ru/powershell/module/…

user26573235 15.08.2024 05:03

Чтобы ответить на комментарий:

@iRon, я прочитал ваш ответ, но (вероятно, по моей вине) с трудом смог применить свой пример, вероятно, главным образом потому, что помещать все в конвейер казалось слишком сложным. Мне следовало упомянуть об этом в своем вопросе, поскольку ваш ответ привел меня к расследованию неэффективности +=. Спасибо :-)

По сути, это шаги, которые необходимо выполнить для исправления сценария:

  1. Удалить инициализацию массива
    $OUACLResults =
  2. Вместо этого присвойте результат итерации непосредственно переменной
    $OUACLResults = foreach ...
  3. Удалить все += задания
    $OUACLResults +=

Результат (не удалось/не удалось полностью протестировать):

$OUs = Get-ADOrganizationalUnit -Filter *

$OUACLResults = foreach ($OU in $OUs) {
        $OUACLs = (get-ACl ad:\$OU.Distinguishedname).access
        Foreach ($ACL in $OUACLs) {
              $ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)
              $Object = new-object -typename psobject
              Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname
              Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype
              Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType
              $Object
        }
}

Поскольку командлет Add-Member довольно многословен и дорог, я рекомендую просто создавать новые объекты PSCustomObject следующим образом:

$OUs = Get-ADOrganizationalUnit -Filter *

$OUACLResults = foreach ($OU in $OUs) {
        $OUACLs = (get-ACl ad:\$OU.Distinguishedname).access
        Foreach ($ACL in $OUACLs) {
              $ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType)
              [PSCustomObject]@{
                  OUDN            = $OU.distinguishedname
                  Inheritancetype = $ACL.Inheritancetype
                  ObjectType      = $ObjectType
              }
        }
}

Другие вопросы по теме