re-arrange 并结合 powershell 自定义 objects
re-arrange and combine powershell custom objects
我有一个系统当前正在从一个即将被替换的单独系统生成的 CSV 文件中读取数据。
导入的 CSV 文件如下所示
PS> Import-Csv .\SalesValues.csv
Sale Values AA BB
----------- -- --
10 6 5
5 3 4
3 1 9
为了替换这个过程,我希望生成一个看起来与上面的 CSV 相同的 object,但我不想继续使用 CSV 文件。
我已经有一个脚本可以从我们的数据库中读取数据并提取我需要使用的数据。我不会详细说明这一点之前相当长的脚本,但实际上它看起来像这样:
$SQLData = Custom-SQLFunction "SELECT * FROM SALES_DATA WHERE LIST_ID = $LISTID"
$SQLData
将包含 ~5000+ 我需要查询的数据行 object。
其中一个 DataRow object 看起来像这样:
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 的内容,创建我需要使用的数据并将其填充到两个单独的 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
}
}
}
}
两个结果 object 看起来像这样:
PS> $AASalesValues
10 5 3 50
-- - - --
17 14 3 1
PS> $BBSalesvalues
3 10 5 4
- -- - -
36 12 11 1
我现在有了我需要的数据,但是我需要以复制 CSV 格式的方式对其进行格式化,以便我可以将其直接传递给另一个现有的 powershell配置为期望 CSV 格式的数据的脚本,但我不想将数据写入文件。
我更愿意将其直接传递到脚本的下一部分。
最终我想要做的是生成一个新的 object/some 输出,它看起来像此 post.
顶部的 Import-Csv
命令的输出
我想要一个新的 object,比如 $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 列下,行匹配 headers原来的两个 objects.
我确实尝试过使用哈希表,但我无法弄清楚如何从动态值创建它们并将它们格式化为我需要它们的外观。
终于到了。
$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。
我假设 $record
包含 $AASalesValues
或 $BBSalesValues
的数据库结果列表,而不是两者,否则您需要某种选择器以避免将一组记录与另一组计数。
按 SaleValue
属性 将记录分组为 :
$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
我有一个系统当前正在从一个即将被替换的单独系统生成的 CSV 文件中读取数据。
导入的 CSV 文件如下所示
PS> Import-Csv .\SalesValues.csv Sale Values AA BB ----------- -- -- 10 6 5 5 3 4 3 1 9
为了替换这个过程,我希望生成一个看起来与上面的 CSV 相同的 object,但我不想继续使用 CSV 文件。
我已经有一个脚本可以从我们的数据库中读取数据并提取我需要使用的数据。我不会详细说明这一点之前相当长的脚本,但实际上它看起来像这样:
$SQLData = Custom-SQLFunction "SELECT * FROM SALES_DATA WHERE LIST_ID = $LISTID"
$SQLData
将包含 ~5000+ 我需要查询的数据行 object。
其中一个 DataRow object 看起来像这样:
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 的内容,创建我需要使用的数据并将其填充到两个单独的 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
}
}
}
}
两个结果 object 看起来像这样:
PS> $AASalesValues 10 5 3 50 -- - - -- 17 14 3 1 PS> $BBSalesvalues 3 10 5 4 - -- - - 36 12 11 1
我现在有了我需要的数据,但是我需要以复制 CSV 格式的方式对其进行格式化,以便我可以将其直接传递给另一个现有的 powershell配置为期望 CSV 格式的数据的脚本,但我不想将数据写入文件。
我更愿意将其直接传递到脚本的下一部分。
最终我想要做的是生成一个新的 object/some 输出,它看起来像此 post.
顶部的Import-Csv
命令的输出
我想要一个新的 object,比如 $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 列下,行匹配 headers原来的两个 objects.
我确实尝试过使用哈希表,但我无法弄清楚如何从动态值创建它们并将它们格式化为我需要它们的外观。
终于到了。
$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。
我假设 $record
包含 $AASalesValues
或 $BBSalesValues
的数据库结果列表,而不是两者,否则您需要某种选择器以避免将一组记录与另一组计数。
按 SaleValue
属性 将记录分组为
$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