Reputation: 41
I have an array, call it $x in powershell.
$x | ft -autosize
d c b
- - -
Apple true
Apple true
Banana
Banana true
Clark true
David true
David true
Eddy
Eddy
I'm trying to combine items. The result I want in this case is:
$x | ft -autosize
d c b
- - -
Apple true true
Banana true
Clark true
David true true
Eddy
Note: the blanks can represent false, but the array is typically blank when false, and TRUE when true. Lines are not always doubled up (as in Clark above)
I can loop thru the array, and collecting each element, 1 by 1, when I find a match (if any), but just keep thinking there has to be a better way.
Upvotes: 1
Views: 299
Reputation: 440112
Group-Object
is indeed the right cmdlet to use:
# Sample input (constructed from CSV data for convenience)
$x = @'
d,c,b
Apple,,true
Apple,true,
Banana,,
Banana,true,
Clark,,true,
David,,true
David,true,
Eddy,,
Eddy,,
'@ | ConvertFrom-Csv
$x | Group-Object d | # Group the array of objects by their .d property
ForEach-Object { # Process each resulting group
# For each .d value, construct a custom object that aggregates
# the .c and .b property values and output it.
[pscustomobject] @{
d = $_.Name # The shared .d value
c = $_.Group.c | Where-Object { $_ } # any non-empty .c values
b = $_.Group.b | Where-Object { $_ } # any non-empty .b values
}
}
The above yields:
d c b
- - -
Apple true true
Banana true
Clark true
David true true
Eddy
Upvotes: 1
Reputation: 1640
The following should clean up your array in PowerShell by leveraging Group-Object
Create an array called $exampleArray
:
$exampleArray = @()
$names = @("Apple", "Banana", "Clark", "David", "Eddy")
$tOrB = @("True","")
#just for an example
1..20 | % {
$object = New-Object PSObject -Property @{
#Get random Name
d = $names[$(Get-Random -Maximum $names.Count)]
#do true / blank -- random
c = $tOrB[$(Get-Random -Maximum $tOrB.Count)]
b = $tOrB[$(Get-Random -Maximum $tOrB.Count)]
}
$exampleArray += $object
}
$exampleArray
We can then group by d
:
#group "combine" by column d
$group = $exampleArray | Group-Object d
Once grouped we can iterate through the grouped names and build a new array called $combined
:
$combined = @()
$group | %{
$object = New-Object PSObject -Property @{
d = $_.Name
}
if($_.Group.c -contains "True")
{
$object | Add-Member -MemberType NoteProperty -Name c -Value "True"
}
else
{
$object | Add-Member -MemberType NoteProperty -Name c -Value ""
}
if($_.Group.b -contains "True")
{
$object | Add-Member -MemberType NoteProperty -Name b -Value "True"
}
else
{
$object | Add-Member -MemberType NoteProperty -Name b -Value ""
}
$combined += $object
}
$combined
Note: If you already have the array loaded (in this case $exampleArray
), you might be better off just doing a Where-Object
off of that array... This is dependent on what exactly you are attempting to accomplish. The answer I provided is most likely over-kill
Upvotes: 1