Группировать и выбирать объекты из CSV в PowerShell - PullRequest
2 голосов
/ 23 марта 2020

У меня есть список пользователей их устройств и их менеджеров. Менеджер и пользователь могут быть дубликатами, но идентификатор устройства уникален. Как получить список, чтобы я мог отправить каждому менеджеру электронное письмо, чтобы сообщить им, сколько и какое подразделение используют его сотрудники? Меня интересуют только люди с двумя или более устройствами.

Требуемый вывод будет выглядеть примерно так (если кто-то захочет дать мне лучшее предложение вывода, я весь слух).

Manager  deviceID
M1        U1=D1 D2, U3=D4 D5

Как выглядит мой код сейчас:

$csv = @"
manager,user,deviceID
M1,U1,D1
M1,U1,D2
M2,U2,D3
M1,U3,D4
M1,U3,D5
"@ -split "`r`n" | ConvertFrom-Csv

$csv | Group-Object -Property Manager |
     Select-Object @{N='Manager';E={($_.Group[0]).Manager}}, 
@{N="User";E={($_.group).user}}, 
@{N="deviceID";E={ foreach($row in $_.Group){ $row.user + ' = ' + $row.deviceID}}} 

Ответы [ 2 ]

2 голосов
/ 23 марта 2020

Поскольку вы говорите, что интересуетесь только перечислением пользователей, которые используют более одного устройства, возможно, это может помочь вам:

$csv = @"
manager,user,deviceID
M1,U1,D1
M1,U1,D2
M2,U2,D3
M1,U3,D4
M1,U3,D5
"@ -split "`r`n" | ConvertFrom-Csv

# first group on Manager
$result = $csv | Group-Object -Property Manager | ForEach-Object {
    $manager = $_.Name
    # next, group the groups on User and select only where a user is mentioned twice or more times
    $_.Group | Group-Object User | Where-Object { $_.Count -gt 1 } | ForEach-Object {
        [PsCustomObject]@{
            Manager = $manager
            User = $_.Name
            Devices = $_.Group.DeviceID -join ' '
        }
    }
}

# output on screen
$result

# output to CSV
$result | Export-Csv -Path 'managerReport.csv' -NoTypeInformation

Вывод:

Manager User Devices
------- ---- -------
M1      U1   D1 D2  
M1      U3   D4 D5
# to separate the results so each manager gets his/her personal report:
$result | Group-Object Manager | ForEach-Object {
    # send an email to the manager. For demo just output to console
    Write-Host "Send mail to manager $($_.Name):" -ForegroundColor Yellow
    $_.Group | Format-Table -AutoSize | Out-String
}
0 голосов
/ 23 марта 2020

Вот подход HashTable:

$managerGroups = $csv | Group-Object -Property manager -AsHashTable

foreach ($item in $managerGroups.GetEnumerator()) {
    $userGroups = $item.Value | Group-Object -Property user -AsHashTable

    & {
        [PSCustomObject]@{
            Manager = $item.Key
            DeviceId = & {
                foreach ($user in $userGroups.GetEnumerator()) {
                    [PSCustomObject]@{
                        User = $user.Key
                        Devices = & {
                            foreach ($device in $user.Value) {
                                $device.deviceID
                            }
                        }
                    }
                }
            }
        }
    } | Select-Object -Property Manager, @{
        Name='DeviceId';
        Expression={
            & {
                foreach ($deviceId in $_.DeviceId) {
                    "$($deviceId.User) = $($deviceId.Devices -join " ")"
                }
            } | Join-String -Separator ", "
        }
    }
}

Вывод:

Manager DeviceId
------- --------
M1      U1 = D1 D2, U3 = D4 D5
M2      U2 = D3

Объяснение:

Вы также можете использовать подход с полным конвейером:

$managerGroups = $csv | Group-Object -Property manager -AsHashTable

$managerGroups.GetEnumerator() | Foreach-Object {
    $manager = $_.Key

    $userGroups = $_.Value | Group-Object -Property user -AsHashTable

    [PSCustomObject]@{
        Manager = $manager
        DeviceId = $userGroups.GetEnumerator() | ForEach-Object {
            [PSCustomObject]@{
                User = $_.Key
                Devices = $_.Value | ForEach-Object {$_.deviceId}
            }
        }
    } | Select-Object -Property Manager, @{
        Name='DeviceId';
        Expression={
            $_.DeviceId | ForEach-Object { 
                "$($_.User) = $($_.Devices -join " ")"
            } | Join-String -Separator ', '
        }
    }
}

Что может быть медленнее, потому что при использовании типов NET или [PSCustomObject], foreach перечисление членов намного быстрее, чем Foreach-Object трубопроводов. Вы можете взглянуть на этот ответ для получения дополнительной информации.

...