AustinJ
AustinJ

Reputation: 33

Powershell looping through Object Variables returning values

Suppose I have object $foo with many (500+) properties.

$foo.q1_sales = "1000"
$foo.q1_expense = "800"
$foo.q2_sales = "1325"
$foo.q2_expense = "1168"
$foo.q3_sales = "895"
$foo.q3_expense = "980"
$foo.q4_sales = "900"
$foo.q4_expense = "875"
...

I want to loop through all properties in $foo and get each value and process it in some way.

$quarters = @("1","2","3","4")

foreach($quarter in $quarters) {
  if($foo.q$quarter_sales -gt $foo.q$quarter_expense) {
    #process data
  }
}

How do I accomplish this? Get-Variable? Get-Member? some combination? Some other way?

Changing the structure of $foo is not an option, unless we can do it programmatically. Sorry.

Upvotes: 2

Views: 8875

Answers (3)

TheMadTechnician
TheMadTechnician

Reputation: 36287

You can use a subexpression to evaluate the property name, such as:

$quarters = @("1","2","3","4")

foreach($quarter in $quarters) {
  if($foo.$("q"+$quarter+"_sales") -gt $foo.$("q"+$quarter+"_expense")) {
    #process data
  }
}

That will evaluate the sub-expressions first, so it figures out "q"+$quarter+"_sales" and then just evaluates $foo.q1_sales as a result.

Upvotes: 2

Anthony Neace
Anthony Neace

Reputation: 26003

Get-Member is a good thought. Here's a generalized attempt to expand on that, so that you can see how it could be done. For my example, my object will be a DateTime:

# Define our object
$object = (Get-Date)

# Get the property names
$properties = $object | Get-Member -MemberType "Property" | % { $_.Name }

# Get our collection of values by iterating the collection of properties
# and for each property getting the value.
$values = $properties | % { $object."$_" }

And then the output would just be the values of each property of DateTime:

$values

Tuesday, October 14, 2014 12:00:00 AM
14
Tuesday
287
17
Local
972
44
10
45
635489054859729996

Ticks             : 638859729996
Days              : 0
Hours             : 17
Milliseconds      : 972
Minutes           : 44
Seconds           : 45
TotalDays         : 0.739420983791667
TotalHours        : 17.746103611
TotalMilliseconds : 63885972.9996
TotalMinutes      : 1064.76621666
TotalSeconds      : 63885.9729996

2014

This assumes that you only want MemberTypes of "Property", so this may not go far enough if you're also after NoteProperty membertypes. Maybe "*Property" for that?

Otherwise, this should work for any arbitrary type with properties. Just swap out my $object with yours.

Upvotes: 1

Frode F.
Frode F.

Reputation: 54871

@TheMadTechnician has already provided the simplest answer. Here's an alternative way:

#Sampledata
$foo = New-Object psobject -Property @{
    q1_sales = "1000"
    q1_expense = "800"
    q2_sales = "1325"
    q2_expense = "1168"
    q3_sales = "895"
    q3_expense = "980"
    q4_sales = "900"
    q4_expense = "875"
}

#Convert to array
$array = $foo.psobject.Properties |
#Group by quarter id(number) so we can create an object per quarter
Group-Object { $_.Name -replace 'q(\d+)_.*', '$1' } |
ForEach-Object {
    New-Object psobject -Property @{
        Quarter = $_.Name
        Sales = [int]($_.Group | Where-Object { $_.Name -match 'sales' } | Select-Object -ExpandProperty Value)
        Expense = [int]($_.Group | Where-Object { $_.Name -match 'expense' } | Select-Object -ExpandProperty Value)
    }
}

#Get quarters with positive result
$array | Where-Object { $_.Sales -gt $_.Expense } | ForEach-Object {
    #process data (sends object through in this sample)
    $_
}

Output:

Sales Expense Quarter
----- ------- -------
 1325    1168 2      
 1000     800 1      
  900     875 4    

Upvotes: 1

Related Questions