Powershell有聚合/减少功能吗?

时间:2014-08-06 15:07:53

标签: powershell

我意识到存在相关问题,但所有答案似乎都是解决问题的核心问题。 powershell是否有一个可以使用scriptblock将数组元素聚合为单个值的操作?这在其他语言中称为aggregatereducefold

我可以很容易地自己编写它,但鉴于它是任何列表处理的基本操作,我会假设有一些我不知道的东西。

所以我正在寻找的是像这样的东西

1..10 | Aggregate-Array {param($memo, $x); $memo * $x}

5 个答案:

答案 0 :(得分:30)

没有任何明显命名为Reduce-Object的东西,但你可以用Foreach-Object实现你的目标:

1..10 | Foreach {$total=1} {$total *= $_} {$total}

BTW还没有Join-Object根据某些匹配属性合并两个数据序列。

答案 1 :(得分:7)

这是我想要开始一段时间的事情。看到这个问题,只写了一个pslinqhttps://github.com/manojlds/pslinq)实用程序。现在的第一个也是唯一一个cmdlet是Aggregate-List,可以像下面这样使用:

1..10 | Aggregate-List { $acc * $input } -seed 1
#3628800

和:

1..10 | Aggregate-List { $acc + $input }
#55

字符串反转:

"abcdefg" -split '' | Aggregate-List { $input + $acc }
#gfedcba

PS:这是一个更多的实验

答案 2 :(得分:5)

如果你需要最大值,最小值,总和或平均值,你可以使用Measure-Object遗憾地它不会处理任何其他聚合方法。

Get-ChildItem | Measure-Object -Property Length -Minimum -Maximum -Average

答案 3 :(得分:1)

最近陷入了类似的问题。这是一个纯粹的Powershell解决方案。不像Javascript版本那样处理数组和字符串中的数组,但可能是一个很好的起点。

function Reduce-Object {
    [CmdletBinding()]
    [Alias("reduce")]
    [OutputType([Int])]
    param(
        # Meant to be passed in through pipeline.
        [Parameter(Mandatory=$True,
                    ValueFromPipeline=$True,
                    ValueFromPipelineByPropertyName=$True)]
        [Array] $InputObject,

        # Position=0 because we assume pipeline usage by default.
        [Parameter(Mandatory=$True,
                    Position=0)]
        [ScriptBlock] $ScriptBlock,

        [Parameter(Mandatory=$False,
                    Position=1)]
        [Int] $InitialValue
    ) 

    begin {
        if ($InitialValue) { $Accumulator = $InitialValue }
    }

    process {
        foreach($Value in $InputObject) {
            if ($Accumulator) {
                # Execute script block given as param with values.
                $Accumulator = $ScriptBlock.InvokeReturnAsIs($Accumulator,  $Value)
            } else {
                # Contigency for no initial value given.
                $Accumulator = $Value
            }
        }
    }

    end {
        return $Accumulator
    }
}

1..10 | reduce {param($a, $b) $a + $b}
# Or
reduce -inputobject @(1,2,3,4) {param($a, $b) $a + $b} -InitialValue 2

答案 4 :(得分:0)

https://github.com/chriskuech/functional上有一个功能模块,它具有一个reduce对象,merge对象,test-equality等。Powershell具有map(foreach-object)和filter(where-object)令人惊讶),但不能减少。 https://medium.com/swlh/functional-programming-in-powershell-876edde1aadb甚至javascript也减少了数组。减速器实际上非常强大。您可以根据它定义地图和过滤器。

1..10 | reduce-object { $a * $b }

3628800

测量对象不能求和[时间跨度]:

1..10 | % { [timespan]"$_" } | Reduce-Object { $a + $b } | ft

Days Hours Minutes Seconds Milliseconds
---- ----- ------- ------- ------------
55   0     0       0       0

合并两个对象:

@{a=1},@{b=2} | % { [pscustomobject]$_ } | Merge-Object -Strategy fail

b a
- -
2 1