Reputation: 33
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
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
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
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