查询PSCustomObject数组以获取具有最大值的行

时间:2020-10-14 00:13:35

标签: arrays powershell sorting

我正在尝试查找具有大于另一行属性的属性的行。示例:

$Array
Name         Value
----         ----
test1         105
test2         101
test3         512   <--- Selects this row as it is the largest value

这是我尝试对此进行“ 1行”处理,但不起作用。

$Array | % { If($_.value -gt $Array[0..($Array.Count)].value){write-host "$_.name is the largest row"}}

当前它什么也不输出。

所需的输出:

"test1 is the largest row"

我很难想象如何在没有严重的意大利面条代码的情况下有效地做到这一点。

3 个答案:

答案 0 :(得分:3)

您可以利用Sort-Object这样按属性“值”对它们进行排名

$array = @(
    [PSCustomObject]@{Name='test1';Value=105}
    [PSCustomObject]@{Name='test2';Value=101}
    [PSCustomObject]@{Name='test3';Value=512}
)

$array | Sort-Object -Property value -Descending | Select-Object -First 1

输出

Name  Value
----  -----
test3   512

要合并您的写主机,您只需运行一个通过foreach选择的主机即可。

$array | Sort-Object -Property value -Descending |
    Select-Object -First 1 | Foreach-Object {Write-host $_.name,"has the highest value"}

test3 has the highest value

或捕获到变量

$Largest = $array | Sort-Object -Property value -Descending | Select-Object -First 1
Write-host $Largest.name,"has the highest value"

test3 has the highest value

答案 1 :(得分:3)

PowerShell具有许多内置功能,可简化此类任务。

如果这实际上是PSCustomObject的数组,则可以执行以下操作:

$Array = 
@(
    [PSCustomObject]@{ Name = 'test1'; Value = 105 }
    [PSCustomObject]@{ Name = 'test2'; Value = 101 }
    [PSCustomObject]@{ Name = 'test3'; Value = 512 }
)

$Largest = ($Array | Sort-Object Value)[-1].Name
Write-host $Largest,"has the highest value"

这将根据Value属性对数组进行排序。然后使用[-1]语法引用最后一个元素,然后返回该对象的name属性。

或者,如果您是纯粹主义者,则可以分配变量,例如:

$Largest = $Array |  Sort-Object Value | Select-Object -Last 1 -ExpandProperty Name

如果要整个对象,只需分别移除.Name-ExpandProperty Name


更新

如前所述,PowerShell提供了一些出色的工具来帮助完成诸如排序和选择数据之类的常见任务。但是,这并不意味着永远不需要循环构造。因此,我想对OP's own answer提出几点意见。

首先,如果确实需要通过索引引用数组元素,请使用传统的For循环,该循环可能类似于:

For( $i = 0; $i -lt $Array.Count; ++$i )
{
    If( $array[$i].Value -gt $LargestValue )
    {
        $LargestName  = $array[$i].Name
        $LargestValue = $array[$i].Value        
    }
}

$i通常用作迭代变量,并且在脚本块中用作数组索引。

第二,在这种情况下,甚至不需要传统循环。您可以坚持使用ForEach循环并在遇到最大值时跟踪最大值。可能看起来像这样:

ForEach( $Row in $array )
{
    If( $Row.Value -gt $LargestValue )
    {
        $LargestName  = $Row.Name
        $LargestValue = $Row.Value        
    }
}

严格来说,您不需要预先分配变量,尽管在其中任何一个变量之前都添加以下内容可能是一个好习惯:

$LargestName  = ""
$LargestValue = 0

在这些示例中,您必须遵循经过稍微修改的Write-Host命令

Write-host $LargestName,"has the highest value"

注意:从Doug Maurer's Fine Answer借用了一些测试代码。考虑到我们的答案是相似的,这只是为了使我的示例更清楚问题并且更易于测试。

答案 2 :(得分:0)

弄清楚了,希望这并不可怕:

$Count = 1
$CurrentLargest = 0
Foreach($Row in $Array) {
        
    # Compare This iteration vs the next to find the largest
    If($Row.value -gt $Array.Value[$Count]){$CurrentLargest = $Row}
    Else {$CurrentLargest = $Array[$Count]}
        
    # Replace the existing largest value with the new one if it is larger than it.
    If($CurrentLargest.Value -gt $Largest.Value){ $Largest = $CurrentLargest }
    
    $Count += 1
}

Write-host $Largest.name,"has the highest value"

编辑:它太糟糕了,请查看其他答案以寻求更好的方法。