简体   繁体   中英

How to group arrays in Powershell?

What is the easy and efficient way to transform an array using PowerShell? An initial array has two properties Number and Color .

Number  Color
1       Red
2       Red
3       Red
4       Red
5       Blue
6       Blue
7       Green
8       Green
9       Green

An output array should like:

Color   Number
Red     1,2,3,4
Blue    5,6
Green   7,8,9
# Input objects.
$objects = @'
Number,Color
1,Red
2,Red
3,Red
4,Red
5,Blue
6,Blue
7,Green
8,Green
9,Green
'@ | ConvertFrom-Csv

$objects |
  Group-Object Color |
    Select-Object @{ n='Color'; e='Name'}, @{ n='Number'; e={ $_.Group.Number } }

The above yields:

Color Number
----- ------
Blue  {5, 6}
Green {7, 8, 9}
Red   {1, 2, 3, 4}

Note: Due to how Group-Object works, the Color values are sorted alphabetically in the output.

See also:

Adding to @mklement0's great answer using Group-Object , we can also group the items into a System.Collections.Hashtable by adding the -AsHashTable switch. To iterate the hashtable keys and values, we have to use System.Collections.Hashtable.GetEnumerator .

$objects = @'
Number,Color
1,Red
2,Red
3,Red
4,Red
5,Blue
6,Blue
7,Green
8,Green
9,Green
'@ | ConvertFrom-Csv

$ht = $objects | Group-Object -Property Color -AsHashTable

$ht.GetEnumerator() | 
    Select-Object @{Name="Color";Expression={$_.Key}}, @{Name="Number";Expression={$_.Value | Select-Object -ExpandProperty Number}}

Output:

Color Number
----- ------
Green {7, 8, 9}
Red   {1, 2, 3, 4}
Blue  {5, 6}

If we want to sort your result by Number , we can use Sort-Object to sort by the first number:

$ht.GetEnumerator() | 
    Select-Object @{Name="Color";Expression={$_.Key}}, @{Name="Number";Expression={$_.Value | Select-Object -ExpandProperty Number}} |
        Sort-Object @{Expression={$_.Number[0]}}

Or use an System.Collections.Specialized.OrderedDictionary to create an ordered hashtable of arrays and maintain order of key insertion:

$ht = [ordered]@{}
foreach ($object in $objects) {
    if (-not ($ht.Keys -contains $object.Color)) {
        $ht[$object.Color] = @()
    }
    $ht[$object.Color] += $object.Number
}

$ht.GetEnumerator() | 
    Select-Object @{Name="Color";Expression={$_.Key}}, @{Name="Number";Expression={$_.Value}} 

Which will output the following:

Color Number
----- ------
Red   {1, 2, 3, 4}
Blue  {5, 6}
Green {7, 8, 9}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM