Манипуляция Массивами Powershell

У меня есть файл экспорта CSV из системы табеля учета рабочего времени в следующем формате:

Paynum, Сотрудник, Дата, Время
123,Joe Blogs,2016-07-10, 08:37: 29
321, Ивор, 2016-07-10, 08:39:31
345, Herr Flick, 2016-07-10, 08:44:05
321, Ивор, 2016-07-10, 12:23: 07
345, Herr Flick, 2016-07-10, 12: 24:15
123,Джо Блоги,2016-07-10, 13:03: 49

Результат, которого я пытаюсь достичь:

Paynum, Сотрудник, Дата, Время#1, Время#2
123, Джо Блоги,2016-07-10,08:37:29,13:03:49
321, Ivor Понятие,2016-07-10,08:39:31,12:23:07
345, Герр Флик,2016-07-10,08:44:05,12:24:15

Я загрузил образец с:

$TimesheetData = @(Import-Csv $MergerFile)

но теперь я полностью потерялся с forпетлями.

2 ответа

    1. Group by Paynum
    2. Сортировка каждой группы по времени
    3. Взять первый элемент в группе
    4. Удалять Time
    5. Добавить Time#1= время первого элемента и Time#2= время второго элемента
    $merged = Import-Csv r:
    	

    Use Group-Object to group the CSV data by employee, then build new objects from the groups:

    Import-Csv 'C:\path\to\input.csv' | Group-Object Employee | ForEach-Object {
      $props = [ordered]@{
        Paynum   = $_.Group[0].Paynum
        Employee = $_.Group[0].Employee
        Date     = $_.Group[0].Date
      }
    
      $i = 1
      $_.Group | Select-Object -Expand Time | ForEach-Object {
        $props["Time#$i"] = $_
        $i++
      }
    
      New-Object -Type PSObject -Property $props
    } | Export-Csv 'C:\path\to\output.csv' -NoType
    

    If the number of records can differ from employee to employee you need to ensure that all generated records have the same number of time fields (or at least that the first record has the maximum number of fields, even if some or all of them are empty), because PowerShell determines the columns to display in tabular output by the first object.

    You can determine the maximum number of time fields from the grouped records:

    $csv      = Import-Csv 'C:\path\to\your.csv' | Group-Object Employee
    $timeCols = $csv | Select-Object -Expand Count |
                Sort-Object |
                Select-Object -Last 1
    

    and use a for loop for adding the time columns:

    $times = $_.Group | Select-Object -Expand Time
    for ($i=1; $i -le $timeCols; $i++) {
      $props["Time#$i"] = $times[$i]
    }
    
    1. Group by Paynum
    2. Sort each group by time
    3. Take the first item in a group
    4. Remove Time
    5. Add Time#1 = first item's time and Time#2 = second item's time
    $merged = Import-Csv r:\1.csv |
        Group Paynum |
        ForEach {
            $sorted = $_.Group | Sort Time
            $sorted[0] |
                Select * -ExcludeProperty Time |
                Select *,
                       @{N='Time#1'; E={$sorted[0].Time}},
                       @{N='Time#2'; E={$sorted[1].Time}}
        }
    $merged | Export-Csv r:\2.csv -NoTypeInformation
    

    .csv |
    Group Paynum |
    ForEach {
    $sorted = $_.Group | Sort Time
    $sorted[0] |
    Select * -ExcludeProperty Time |
    Select *,
    @{N='Time#1'; E={$sorted[0].Time}},
    @{N='Time#2'; E={$sorted[1].Time}}
    }
    $merged | Export-Csv r:.csv -NoTypeInformation

  1. Используется Group-Objectдля группировки данных CSV по сотрудникам, а затем создания новых объектов из групп:

    Import-Csv 'C:\path\to\input.csv' | Group-Object Employee | ForEach-Object {
      $props = [ordered]@{
        Paynum   = $_.Group[0].Paynum
        Employee = $_.Group[0].Employee
        Date     = $_.Group[0].Date
      }
    
      $i = 1
      $_.Group | Select-Object -Expand Time | ForEach-Object {
        $props["Time#$i"] = $_
        $i++
      }
    
      New-Object -Type PSObject -Property $props
    } | Export-Csv 'C:\path\to\output.csv' -NoType
    

    Если количество записей может отличаться от сотрудника к сотруднику, необходимо убедиться, что все сгенерированные записи имеют одинаковое количество полей времени (или, по крайней мере, что первая запись имеет максимальное количество полей, даже если некоторые или все из них пусты), поскольку PowerShell определяет столбцы для отображения в табличных выходных данных первым объектом.

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

    $csv      = Import-Csv 'C:\path\to\your.csv' | Group-Object Employee
    $timeCols = $csv | Select-Object -Expand Count |
                Sort-Object |
                Select-Object -Last 1
    

    и используйте forцикл для добавления столбцов времени:

    $times = $_.Group | Select-Object -Expand Time
    for ($i=1; $i -le $timeCols; $i++) {
      $props["Time#$i"] = $times[$i]
    }