переупорядочить и объединить пользовательские объекты powershell - PullRequest
0 голосов
/ 06 ноября 2018

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

Импортированный файл CSV выглядит следующим образом

PS> Import-Csv .\SalesValues.csv
Sale Values AA BB
----------- -- --
10          6  5
5           3  4
3           1  9

Чтобы заменить этот процесс, я надеюсь создать объект, который выглядит идентично CSV выше, но я не хочу продолжать использовать файл CSV.

У меня уже есть скрипт, который считывает данные из нашей базы данных и извлекает данные, которые мне нужно использовать. Я не буду подробно описывать довольно длинный скрипт, который предшествует этому пункту, но в действительности он выглядит так:

$SQLData = Custom-SQLFunction "SELECT * FROM SALES_DATA WHERE LIST_ID = $LISTID"

$SQLData будет содержать ~ 5000 + объектов DataRow, которые мне нужно запросить.

Один из этих объектов DataRow выглядит примерно так:

lead_id                 : 123456789
entry_date              : 26/10/2018 16:51:16
modify_date             : 01/11/2018 01:00:02
status                  : WRONG
user                    : mrexample
vendor_lead_code        : TH1S15L0NGC0D3
source_id               : A543212
list_id                 : 333004
list_name               : AA Some Text
gmt_offset_now          : 0.00
SaleValue               : 10

list_name будет иметь префикс AA или BB.

SaleValue может быть любым целым числом от 3 и выше, однако на самом деле крайне маловероятно, что оно будет больше 100 (поскольку это ежемесячное пожертвование) и будет одним из 3,5,10 в подавляющем большинстве случаев.

У меня уже есть скрипт, который берет содержимое списка list_name, создает и заполняет данные, которые мне нужно использовать, в два отдельных объекта psobject ($AASalesValues и $BBSalesValues), которые объединяют общее число «SaleValue» в наборе данных.

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

foreach ($record in $SQLData) {
    if ($record.list_name -match "BB") {
        if ($record.SaleValue -gt 0) {
            if ($BBSalesValues | Get-Member -Name $($record.SaleValue) -MemberType Properties) {
                $BBSalesValues.$($record.SaleValue) = $BBSalesValues.$($record.SaleValue)+1
            } else {
                $BBSalesValues | Add-Member -Name $($record.SaleValue) -MemberType NoteProperty -Value 1
            }
        }
    }    
}

Два результирующих объекта выглядят так:

PS> $AASalesValues
10  5 3 50
--  - - --
17 14 3  1

PS> $BBSalesvalues
 3 10  5 4
 - --  - -
36 12 11 1

Теперь у меня есть данные, которые мне нужны, однако мне нужно отформатировать их так, чтобы реплицировал формат CSV, чтобы я мог передать их непосредственно другому существующему сценарию powershell, настроенному на ожидание данные в формате, в котором находится CSV, но я не хочу записывать данные в файл.

Я бы предпочел передать это непосредственно следующей части сценария.

В конечном итоге я хочу создать новый объект / некоторый вывод, который будет выглядеть как вывод команды Import-Csv в верхней части этого поста.

Мне бы хотелось, чтобы новый объект, скажем $OverallSalesValues, выглядел так:

PS>$overallSalesValues
Sale Values  AA  BB
50           1   0
10           17  12
5            14  11
4            0   1
3            3   36

В приведенном выше примере значения из $AASalesValues перечислены под столбцом AA, значения из $BBSalesValues перечислены под столбцом BB, строки которого соответствуют заголовкам двух исходных объектов.

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

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Я собираюсь предположить, что $record содержит список результатов базы данных для $AASalesValues или $BBSalesValues, но не для обоих, в противном случае вам потребуется какой-то селектор, чтобы избежать подсчета записей одной группы с другая группа.

Сгруппируйте записи по их SaleValue свойству как Рекомендуемые LotPings :

$BBSalesValues = $record | Group-Object SaleValue -NoElement

Это даст вам список SaleValue значений с их соответствующим количеством.

PS> $BBSalesValues
Count Name
----- ----
   36 3
   12 10
   11 5
    1 4

Затем вы можете обновить данные CSV с помощью следующих значений:

$file = 'C:\path\to\data.csv'

# read CSV into a hashtable mapping the sale value to the complete record
# (so that we can lookup the record by sale value)
$csv = @{}
Import-Csv $file | ForEach-Object {
    $csv[$_.'Sale Values'] = $_
}

# Add records for missing sale values
$($AASalesValues; $BBSalesValues) | Select-Object -Expand Name -Unique | ForEach-Object {
    if (-not $csv.ContainsKey($_)) {
        $csv[$_] = New-Object -Type PSObject -Property @{
            'Sale Values' = $_
            'AA'          = 0
            'BB'          = 0
        }
    }
}

# update records with values from $AASalesValues
$AASalesValues | ForEach-Object {
    [int]$csv[$_.Name].AA += $_.Count
}

# update records with values from $BBSalesValues
$BBSalesValues | ForEach-Object {
    [int]$csv[$_.Name].BB += $_.Count
}

# write updated records back to file
$csv.Values | Export-Csv $file -NoType

Даже с вашим обновленным вопросом подход будет почти таким же, вы просто добавите еще один уровень группировки для сбора продаж:

$sales = @{}
$record | Group-Object {$_.list_name.Split()[0]} | ForEach-Object {
    $sales[$_.Name] = $_.Group | Group-Object SaleValue -NoElement
}

и затем настройте объединение примерно так:

$file = 'C:\path\to\data.csv'

# read CSV into a hashtable mapping the sale value to the complete record
# (so that we can lookup the record by sale value)
$csv = @{}
Import-Csv $file | ForEach-Object {
    $csv[$_.'Sale Values'] = $_
}

# Add records for missing sale values
$sales.Values | Select-Object -Expand Name -Unique | ForEach-Object {
    if (-not $csv.ContainsKey($_)) {
        $prop = @{'Sale Values' = $_}
        $sales.Keys | ForEach-Object {
            $prop[$_] = 0
        }
        $csv[$_] = New-Object -Type PSObject -Property $prop
    }
}

# update records with values from $sales
$sales.GetEnumerator() | ForEach-Object {
    $name = $_.Key
    $_.Value | ForEach-Object {
        [int]$csv[$_.Name].$name += $_.Count
    }
}

# write updated records back to file
$csv.Values | Export-Csv $file -NoType
0 голосов
/ 07 ноября 2018

Наконец добрались.

$TotalList = @()
foreach($n in 3..200){
    if($AASalesValues.$n -or $BBSalesValues.$n){
        $AACount = $AASalesValues.$n
        $BBcount = $BBSalesValues.$n

        $values = [PSCustomObject]@{
            'Sale Value'= $n
            AA = $AACount
            BB = $BBcount
            }
        $TotalList += $values
        }
    }
$TotalList

производит вывод

Sale Value AA BB
---------- -- --
         3  3 36
         4     2
         5 14 11
        10 18 12
        50  1   

Просто нужно добавить немного, чтобы включить значения '0' вместо $ null.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...