Does Powershell have an Aggregate/Reduce function?

This is something I wanted to start for a while. Seeing this question, just wrote a pslinq (https://github.com/manojlds/pslinq) utility. The first and only cmdlet as of now is Aggregate-List, which can be used like below:

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

Sum:

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

String reverse:

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

PS: This is more an experiment


Ran into a similar issue recently. Here's a pure Powershell solution. Doesn't handle arrays within arrays and strings like the Javascript version does but maybe a good starting point.

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

There is not anything so obviously named as Reduce-Object but you can achieve your goal with Foreach-Object:

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

BTW there also isn't a Join-Object to merge two sequences of data based on some matching property.


If you need Maximum, Minimum, Sum or Average you can use Measure-Object sadly it dosen´t handle any other aggregate method.

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

Tags:

Powershell