Where-Object не находит ни одного экземпляра пользовательского объекта, но находит несколько его экземпляров. Возможная ошибка?
Я работаю над сценарием, который выполняет вызов API и возвращает результат в формате JSON и обрабатывается как массив пользовательских объектов в Powershell. Одним из свойств пользовательского объекта является Статус, поэтому для каждого уникального статуса я хотел получить счетчик объекта с этим статусом. Я был удивлен, когда мой код для определенных статусов вернул счетчик 0, потому что если бы его не было с самого начала, мой скрипт не искал бы этот статус.
Затем я заметил, что код работает, когда существует более одного объекта со статусом, но когда существует только один объект с таким статусом, мой код не может найти его с помощью Where-Object. Если я перебираю массив пользовательских объектов и выполняю оценку if(), он находит все состояния, включая те, которые имели только один объект.
Я что-то здесь упускаю или это ошибка? Мой ноутбук работает под управлением PS 5.1, я также пробовал его на сервере W2K12 под управлением PS 4.0, и я получаю то же самое.
Я также смог смоделировать это (удалив части API и JSON) в коде ниже:
$testArray = @()
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name1' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name2' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status2' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name3' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name4' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name5' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name6' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name7' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name8' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name9' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name10' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name11' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name12' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name13' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status1' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name14' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name15' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
$testObject = New-Object -TypeName PSObject
$testObject | Add-Member -type NoteProperty -name Name -value 'Name16' -Force
$testObject | Add-Member -type NoteProperty -name Status -value 'Status3' -Force
$testArray += $testObject
Write-Host "`n`nPowerShell version:"
$PSVersionTable.PSVersion
Write-Host "`n`nUsing Where-Object on the array"
$uniqueStatuses = ( $testArray.Status | sort | Get-Unique )
foreach ($status in $uniqueStatuses)
{
$status
($testArray | Select-Object | Where-Object { $_.Status -eq $status }).Count
}
Write-Host "`n`nLooping through the array"
foreach ($status in $uniqueStatuses)
{
$status
[int]$count = 0
foreach ($object in $testArray)
{
if ($object.Status -eq $status)
{
$count++
}
}
$count
}
В приведенном выше примере кода статус Status2 появляется только в одном из пользовательских объектов, а Where-Object по какой-то причине не находит его, а использует foreach.
Когда я запускаю код выше, я получаю:
Версия PowerShell:
Major Minor Build Revision
5 1 14393 0
Использование Where-Object в массиве
STATUS1
8
Status2
СОСТОЯНИЕ 3
7
Цикл по массиву
STATUS1
8
Status2
1
СОСТОЯНИЕ 3
7
1 ответ
В первом примере (используя Where-Object
), нет никакой гарантии, что конвейер приведет к сбору - с Status2
он возвращает только один объект, поэтому Count
ничего не возвращает.
Используйте оператор подвыражения массива @()
и вы увидите правильный счет:
$uniqueStatuses = ( $testArray.Status | sort | Get-Unique )
foreach ($status in $uniqueStatuses)
{
$status
@($testArray | Select-Object | Where-Object { $_.Status -eq $status }).Count
}