Как сложить несколько элементов в объекте в PowerShell? - PullRequest
21 голосов
/ 14 мая 2011

у меня есть:

$report.gettype().name
Object[]

echo $report

Item                       Average
--                         -------
orange                     0.294117647058824
orange                    -0.901960784313726
orange                    -0.901960784313726
grape                      9.91335740072202
grape                      0
pear                       3.48736462093863
pear                      -0.0324909747292419
pear                      -0.0324909747292419
apple                     12.1261261261261
apple                     -0.0045045045045045

Я хочу создать переменную $ total (например, хеш-таблицу), которая содержит сумму столбца «Среднее» для каждого элемента, например,

echo $total

orange  -1.5097
grape    9.913
pear     3.423
apple   12.116

Сейчас я думаю о циклическом просмотре $ report, но это ужасно уродливо, и я ищу что-то более элегантное, чем следующая отправная точка (неполная):

$tmpPrev = ""
foreach($r in $report){
    $tmp = $r.item
    $subtotal = 0
    if($tmp <> $tmpPrev){
        $subtotal += $r.average
    }

Как я мог это сделать?

Ответы [ 3 ]

52 голосов
/ 14 мая 2011

Командлеты Group-Object и Measure-Object помогают решить задачу в PowerShell-режиме:

Код:

# Demo input
$report = @(
    New-Object psobject -Property @{ Item = 'orange'; Average = 1 }
    New-Object psobject -Property @{ Item = 'orange'; Average = 2 }
    New-Object psobject -Property @{ Item = 'grape'; Average = 3 }
    New-Object psobject -Property @{ Item = 'grape'; Average = 4 }
)

# Process: group by 'Item' then sum 'Average' for each group
# and create output objects on the fly
$report | Group-Object Item | %{
    New-Object psobject -Property @{
        Item = $_.Name
        Sum = ($_.Group | Measure-Object Average -Sum).Sum
    }
}

Вывод:

Sum Item
--- ----
  3 orange
  7 grape
9 голосов
/ 14 мая 2011

У меня есть другое решение для командной строки.

Учитывая, что $ report

$groupreport = $report | Group-Object -Property item -AsHashTable

равно

Name     Value
----     -----
grape    {@{Item=grape; Average=9.91335740072202}, @{Item=grape; Average=0}}
orange   {@{Item=orange; Average=0.294117647058824}, @{Item=orange; Average=-0.901960784313726...
apple    {@{Item=apple; Average=12.1261261261261}, @{Item=apple; Average=-0.0045045045045045}}
pear     {@{Item=pear; Average=3.48736462093863}, @{Item=pear; Average=-0.0324909747292419}, @...

тогда

$tab=@{}
$groupreport.keys | % {$tab += @{$_ = ($groupreport[$_] | measure-object -Property average -sum)}}

дает

PS> $tab["grape"]

Count    : 2
Average  :
Sum      : 9,91335740072202
Maximum  :
Minimum  :
Property : Average

PS> $tab["grape"].sum
9,91335740072202

Кажется коротким и пригодным для использования.

Резюме

$groupreport = $report | Group-Object -Property item -AsHashTable
$tab = @{}
$groupreport.keys | % {$tab += @{$_ = ($groupreport[$_] | measure-object -Property average -sum)}}
$tab.keys | % {write-host $_ `t $tab[$_].sum}
5 голосов
/ 14 мая 2011

Я не знаю, сможете ли вы избавиться от зацикливания. Как насчет:

$report | % {$averages = @{}} {
    if ($averages[$_.item]) {
        $averages[$_.item] += $_.average
    }
    else {
        $averages[$_.item] = $_.average
    }
} {$averages}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...