重新排列并合并Powershell自定义对象

时间:2018-11-06 18:01:10

标签: powershell object hashtable

我有一个系统,该系统当前从将要替换的单独系统产生的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将以AABB为前缀。

SaleValue可以是3以上的任何整数,但是实际上极不可能高于100(因为这是每月捐赠),并且在大多数情况下将是3、5、10之一。

我已经有了一个脚本,该脚本采用list_name的内容,创建并将需要使用的数据填充到两个单独的psobjects($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格式的方式对其进行格式化,以便可以将其直接传递给配置为期望数据采用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

在上面的示例中,AA列下列出了$AASalesValues的值,BB列下列出了$BBSalesValues的值,其中的行与两个原始对象的标题匹配。 / p>

我确实使用哈希表进行了尝试,但是我无法弄清楚如何从动态值创建它们并将它们格式化为我需要的外观。

2 个答案:

答案 0 :(得分:0)

终于到了。

$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。

答案 1 :(得分:0)

我将假设$record包含$AASalesValues$BBSalesValues的数据库结果列表,不能同时包含两者,否则,您需要某种选择器来避免计算一组和另一组的记录。

按记录的SaleValue属性将记录分组为LotPings suggested

$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