Нужен более быстрый способ в Powershell объединять большие массивы в один двумерный массив - PullRequest
0 голосов
/ 11 июля 2020

Я столкнулся с ситуацией, когда мне нужен очень быстрый метод для объединения нескольких больших массивов через Powershell. Первоначально данные поступают из json -входа, но для объяснения моей проблемы я приведу небольшой фрагмент кода, который создает аналогичную ситуацию:

$columnCount = 10 # this number is NOT fixed!
$rowCount = 10KB
$allData = @()
$titles = @()

# create sample input data for the scenario that I need to solve:
foreach($i in 1..$columnCount) {
    $titles += "Column$i"
    $columnData = ,"$i" * $rowCount
    $alldata += ,$columnData
}

Теперь мне нужен быстрый способ объединить эти 10 одномерные массивы с их данными на столбец в один двухмерный массив с правильными названиями столбцов.

Я начал с этого кода:

$t = [System.Diagnostics.Stopwatch]::StartNew()

$result = [System.Collections.ArrayList]::new()
$columnMaxId = $columnCount-1
$rowMaxId = $allData[0].count-1
foreach($row in 0..$rowMaxId) {
    $line = [PsObject]::new()
    foreach($column in 0..$columnMaxId) {
        $line | Add-Member -MemberType NoteProperty -Name $titles[$column] -Value $allData[$column][$row]
    }
    $null = $result.Add($line)
}

$t.Stop()
$t.Elapsed.TotalSeconds

Время выполнения составляло 12 2429499 секунд с приведенные выше демонстрационные данные. Поскольку мне приходилось запускать такого рода задачи очень часто, а реальные данные иногда бывают даже больше и содержат до 30 столбцов, это решение недостаточно быстрое. Как мне это ускорить?

1 Ответ

2 голосов
/ 11 июля 2020

В итоге я использовал таблицы данных для вышеуказанной задачи. Добавление строк в таблицу данных позволяет передавать массив значений для каждой строки, и таким образом я могу обрабатывать динамическую c длину каждой строки. Вот мой код:

$t = [System.Diagnostics.Stopwatch]::StartNew()

$table = [System.Data.Datatable]::new()
foreach($title in $titles) {[void]$table.Columns.Add($title)}
$columnMaxId = $columnCount-1
foreach($row in 0..($rowCount-1)){
    $dataRow = [System.Collections.ArrayList]::new()
    foreach($column in 0..$columnMaxId){
        [void]$dataRow.Add($allData[$column][$row])
    }
    [void]$table.Rows.Add([array]$dataRow)
}

$t.Stop()
$t.Elapsed.TotalSeconds

Время выполнения вышеуказанного демонстрационного ввода теперь составляет 0,3300486 секунд.

...