J. DuBois
J. DuBois

Reputation: 41

Combine Powershell arrays

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

Answers (2)

mklement0
mklement0

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

jrider
jrider

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

Related Questions