2

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.

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

@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    

Comments

1

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.

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.