Манипулирование массивом Powershell

#arrays #powershell #csv

#массивы #powershell #csv

Вопрос:

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

Число, сотрудник, дата, время
123,Joe Blogs,2016-07-10,08:37:29
321,Ivor Notion,2016-07-10,08:39:31
345, герр Флик,2016-07-10,08:44:05
321,Ivor Notion,2016-07-10,12:23:07
345, герр Флик, 2016-07-10,12:24:15
123, Joe Blogs,2016-07-10,13:03:49

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

Число, сотрудник, Дата, время # 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 циклах.

Комментарии:

1. Можете ли вы опубликовать цикл for?

2. У меня был цикл foreach, но оттуда полностью потерян сюжет. foreach ($row в $TimesheetData) { $row. Paynum $row.Employee $row. Дата $строка. Время }

Ответ №1:

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

 Import-Csv 'C:pathtoinput.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:pathtooutput.csv' -NoType
  

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

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

 $csv      = Import-Csv 'C:pathtoyour.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]
}
  

Комментарии:

1. @ Ansgar Wiechers — Ваш скрипт работает отлично. Я обнаружил, что мне не нужно считать дополнительные времена, поскольку скрипт добавляет дополнительный столбец с номером «Time #» . Я нашел, добавив дополнительные элементы группы (например, Manager = $ _.Group[0].Manager ) Я могу обрабатывать любые дополнительные исходные столбцы. Единственный вопрос, который у меня есть, — как мне сгруппироваться на несколько дней, чтобы каждый день находился в отдельной строке?

2. Group-Object Employee, Date

Ответ №2:

  1. Группировать по Paynum
  2. Сортировка каждой группы по времени
  3. Возьмите первый элемент в группе
  4. Удалить Time
  5. Добавить Time#1 = время первого элемента и Time#2 = время второго элемента

 $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
  

Комментарии:

1. ваш сценарий работает отлично, но альтернатива немного более гибкая, поскольку стойки ворот теперь перемещены — тем не менее, спасибо за помощь.