2

I'm trying to find the row with an attribute that is larger than the other row's attributes. Example:

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

Here is my attempt to '1 line' this but It doesn't work.

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

Currently it outputs nothing.

Desired Output:

"test1 is the largest row"

I'm having trouble visualizing how to do this efficiently with out some serious spaghetti code.

3 Answers 3

3

You could take advantage of Sort-Object to rank them by the property "Value" like this

$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

Output

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

To incorporate your write host you can just run the one you select through a 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

Or capture to a variable

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

test3 has the highest value
Sign up to request clarification or add additional context in comments.

1 Comment

THIS is exactly what I was looking for. I knew there had to be a simple way to do it. Thank you Doug!
3

PowerShell has many built in features to make tasks like this easier.

If this is really an array of PSCustomObjects you can do something like:

$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"

This will sort your array according to the Value property. Then reference the last element using the [-1] syntax, then return the name property of that object.

Or if you're a purist you can assign the variable like:

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

If you want the whole object just remove .Name & -ExpandProperty Name respectively.


Update:

As noted PowerShell has some great tools to help with common tasks like sorting & selecting data. However, that doesn't mean there's never a need for looping constructs. So, I wanted to make a couple of points about the OP's own answer.

First, if you do need to reference array elements by index use a traditional For loop, which might look something like:

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

$i is commonly used as an iteration variable, and within the script block is used as the array index.

Second, even the traditional loop is unnecessary in this case. You can stick with the ForEach loop and track the largest value as and when it's encountered. That might look something like:

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

Strictly speaking you don't need to assign the variables beforehand, though it may be a good practice to precede either of these with:

$LargestName  = ""
$LargestValue = 0

In these examples you'd have to follow with a slightly modified Write-Host command

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

Note: Borrowed some of the test code from Doug Maurer's Fine Answer. Considering our answers were similar, this was just to make my examples more clear to the question and easier to test.

Comments

0

Figured it out, hopefully this isn't awful:

$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"

Edit: its awful, look at the other answers for a better way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.