MapReduceFilter.psm1

<#
 .Synopsis
  Perform functional-style operations on each element of a sequence or stream of objects in a Powershell pipeline
 
 .Description
  Apply the given ScriptBlock expression to each member of the pipelined InputObject.
 
 .Parameter Expression
  The anonymous (in-place) or named (as variable) single-argument lambda function to be applied to each InputObject element. This must have a single-argument parameter block.
 
 .Parameter InputObject
  The sequence or stream of Objects from the Powershell pipeline.
 
 .Example
   # Double each element of a list.
   @(1,2,3) | Convert-Map { param($it) 2 * $it }
   2
   4
   6
 
 .Example
   # First double each element of a list and then add 3 to each element of the new list.
   @(1,2,3) | Convert-Map { param($it) 2 * $it } | Convert-Map { param($doubled) $doubled + 3 }
   5
   7
   9
#>

function Convert-Map
{
    [cmdletbinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ $_.Ast.ParamBlock.Parameters.Count -eq 1 })]
        [Scriptblock] $Expression,
 
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true)]
        [object[]] $InputObject
    )

    begin { if ( $InputObject ) { $Accumulator = $InputObject | % { &$Expression $_ } } else { $Accumulator = @() } }

    process { if ( $input ) { $Accumulator = $Accumulator + @( &$Expression $_ ) } }

    end { $Accumulator }
}

<#
 .Synopsis
  Perform functional-style folding or reducing operations on a sequence or stream of objects in a Powershell pipeline
 
 .Description
  Apply the given ScriptBlock expression to an accumulating value using each member of the pipelined InputObject.
 
 .Parameter Expression
  The anonymous (in-place) or named (as variable) single-argument lambda function to be applied to each InputObject element. This must have a double-argument parameter block.
 
 .Parameter InputObject
  The sequence or stream of Objects from the Powershell pipeline.
 
 .Example
   # Reduce a list to the sum of its elements.
   @(1,2,3) | Convert-Reduce { param($acc,$it) $acc + $it } -Accumulator 0
   6
 
 .Example
   # Apply a set of XSLT Transforms to an initial XML document, yielding the transformed XML after each transformation has been applied to the prior transformation
   @( $stylesheet1, $stylesheet2, $stylesheet3 ) | Convert-Reduce { param($acc,$it) Transform-Xslt -Output $acc -Stylesheet $it -Input $acc } -Accumulator $originalXml
#>
 
function Convert-Reduce
{
    [cmdletbinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ $_.Ast.ParamBlock.Parameters.Count -eq 2 })]
        [Scriptblock] $Expression,
 
        [Parameter(Mandatory)]
        [Object] $Accumulator,

    [Parameter(Mandatory = $true,
        ValueFromPipeline = $true)]
        [object[]] $InputObject
    )

    begin { if ( $InputObject ) { $Accumulator = Convert-ListReduce $Expression -Accumulator $Accumulator -InputObject $InputObject } }

    process { $Accumulator = &$Expression $Accumulator $_ }

    end { $Accumulator }
}

function Convert-ListReduce
{
    [cmdletbinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ $_.Ast.ParamBlock.Parameters.Count -eq 2 })]
        [Scriptblock] $Expression,
 
        [Parameter(Mandatory)]
        [Object] $Accumulator,

    [Parameter(Mandatory = $true,
        ValueFromPipeline = $true)]
        [object[]] $InputObject
    )

    begin { $InputObject | Convert-Reduce $Expression -Accumulator $Accumulator }
}

<#
 .Synopsis
  Perform functional-style filter-to-select operations on a sequence or stream of objects in a Powershell pipeline
 
 .Description
  Apply the given ScriptBlock expression to each member of the pipelined InputObject, selecting those for which the expression is True.
 
 .Parameter Expression
  The anonymous (in-place) or named (as variable) single-argument lambda function to be applied to each InputObject element. This must have a single-argument parameter block.
 
 .Parameter InputObject
  The sequence or stream of Objects from the Powershell pipeline.
 
 .Example
   # Pick out the 2's from a stream
   @(1,2,3) | Search-Select { param($it) $it -eq 2 }
   2
 
 .Example
   # Pick out the 2's from a list
   Search-Select { param($it) $it -eq 2 } -InputObject @(1,2,3)
   2
#>
 
function Search-Select
{
    [cmdletbinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ $_.Ast.ParamBlock.Parameters.Count -eq 1 })]
        [Scriptblock] $Expression,
 
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true)]
        [object[]] $InputObject
    )

    begin { if ( $InputObject ) { $InputObject | Where-Object { ( &$Expression $_ ) -eq $true } } }

    process { if ( &$Expression $_ ) { $_ } }
}

<#
 .Synopsis
  Perform functional-style filter-to-reject operations on a sequence or stream of objects in a Powershell pipeline
 
 .Description
  Apply the given ScriptBlock expression to each member of the pipelined InputObject, rejecting those for which the expression is True.
 
 .Parameter Expression
  The anonymous (in-place) or named (as variable) single-argument lambda function to be applied to each InputObject element. This must have a single-argument parameter block.
 
 .Parameter InputObject
  The sequence or stream of Objects from the Powershell pipeline.
 
 .Example
   # Reject the 2's from a stream
   @(1,2,3) | Search-Reject { param($it) $it -eq 2 }
   1
   3
 
 .Example
   # Reject out the 2's from a list
   Search-Reject { param($it) $it -eq 2 } -InputObject @(1,2,3)
   1
   3
#>
 
function Search-Reject
{
    [cmdletbinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ $_.Ast.ParamBlock.Parameters.Count -eq 1 })]
        [Scriptblock] $Expression,
 
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true)]
        [object[]] $InputObject
    )

    begin { if ( $InputObject ) { $InputObject | Where-Object { ( &$Expression $_ ) -ne $true } } }

    process { if ( -Not ( &$Expression $_ ) ) { $_ } }
}