寻求快速、简洁和清晰的代码的平衡组合,以从对象数组中加值



给定以下对象数组:

Email               Domain       Tally
-----               -----        -----
email1@domainA.com  domainA.com  4
email1@domainB.com  domainB.com  1
email2@domainC.com  domainC.com  6
email4@domainA.com  domainA.com  1

我想"按"域分组并随时添加 Tally。最终结果是这样的:

Domain       Tally
------       -----
domainA.com  5
domainB.com  1
domainC.com  6

我有一些有用的东西,但我觉得它太复杂了。

$AllTheAddresses = Get-AllTheAddresses
$DomainTally = @()
foreach ($Addy in $AllTheAddresses)
{
    if ($DomainTally | Where-Object {$_.RecipientDomain -eq $Addy.RecipientDomain})
    {
        $DomainTally |
            Where-Object {$_.RecipientDomain -eq $Addy.RecipientDomain} |
            ForEach-Object {$_.Tally += $Addy.Tally }
    }
    else
    {
        $props = @{
            RecipientDomain = $Addy.RecipientDomain
            Tally = $Addy.Tally
        }
        $DomainTally += New-Object -TypeName PSObject -Property $props
    }
}

在我的示例中,我将地址创建为哈希表,但 PowerShell 将允许你通过类似于对象的.Property来引用键。

如果您真的只是按域求和,那么似乎您不需要比哈希表更复杂的东西来创建您的运行总计。

基本总结:

$Tally = @{}
$AllTheAddresses | ForEach-Object {
    $Tally[$_.Domain] += $_.Tally
}

使用此示例数据...

$AllTheAddresses = @( 
    @{ Email = "email1@domainA.com"; Domain = "domainA.com"; Tally = 4 };
    @{ Email = "email1@domainB.com"; Domain = "domainB.com"; Tally = 1 };
    @{ Email = "email1@domainC.com"; Domain = "domainC.com"; Tally = 6 };
    @{ Email = "email1@domainA.com"; Domain = "domainA.com"; Tally = 1 }
    )

你会得到这个输出:

PS> $tally
Name                           Value                                                                                    
----                           -----                                                                                    
domainC.com                    6                                                                                        
domainB.com                    1                                                                                        
domainA.com                    5            

这是一个"PowerShellic"版本,请注意数据的管道和流动。你当然可以把它写成一行(我最初是在这里发布答案之前做的)。 其中"更好"的部分是使用组对象和度量对象 cmdlet。 请注意,没有条件,同样是因为该示例使用管道。

$AllTheAddresses | 
Group-Object -Property Domain |
ForEach-Object {
    $_ | 
    Tee-Object -Variable Domain |
    Select-Object -Expand Group |
    Measure-Object -Sum Tally |
    Select-Object -Expand Sum |
    ForEach-Object { 
        New-Object -TypeName PSObject -Property @{
            'Domain' = $Domain.Name
            'Tally' = $_
        }
    } |
    Select-Object Domain, Tally
}

更简洁的版本

$AllTheAddresses | 
Group Domain |
% {
    $_ | 
    Tee-Object -Variable Domain |
    Select -Expand Group |
    Measure -Sum Tally |
    Select -Expand Sum |
    % { 
        New-Object PSObject -Property @{
            'Domain' = $Domain.Name
            'Tally' = $_
        }
    } |
    Select Domain, Tally
}

Group-Object绝对是要走的路。

为了简洁

起见:
Get-AllTheAddresses |Group-Object Domain |Select-Object @{N='Domain';E={$_.Name}},@{N='Tally';E={($_.Group.Tally |Measure-Object).Sum}}

最新更新