PoshCode Archive  Artifact [7eb0bf409f]

Artifact 7eb0bf409f69243defe0235b855db97c55dfaac9bf54a7bf379bad0c855d4008:

  • File Get-Sequence.ps1 — part of check-in [3a7ef64b71] at 2018-06-10 14:12:00 on branch trunk — Emulates the Python functions: Map, Reduce and Filter. (user: Vince Ypma size: 5134)

# encoding: utf-8
# api: powershell
# title: Get-Sequence
# description: Emulates the Python functions: Map, Reduce and Filter.
# version: 0.1
# type: function
# author: Vince Ypma
# license: CC0
# function: Get-Sequence
# x-poshcode-id: 6276
# x-archived: 2016-11-18T01:25:59
# x-published: 2016-04-01T08:48:00
#
#
#requires -Version 3

function Get-Sequence
{
  <#
    .SYNOPSIS
        Performs various transformations on the data.
    .DESCRIPTION
        Performs simple transformations on data without needing to define functions for each transformation.

        Rather than declaring a function that describes how to transform each element, what if we could just
        apply a simple transformation to each element that didn’t require a function definition?
        This can be accomplished with lambda functions.

        A lambda function is a nameless (i.e. anonymous) function that accepts arguments and returns the result
        of a simple operation that doesn’t affect variables outside of its scope. In PowerShell lingo, a lambda
        function is simply a script block with a ‘param’ declaration.
    .EXAMPLE
        $IntArray = @(1, 2, 3, 4, 5, 6)
 
        $Double = { param($x) $x * 2 }
        $Sum = { param($x, $y) $x + $y }
        $Product = { param($x, $y) $x * $y }
        $IsEven = { param($x) $x % 2 -eq 0 }
 
        Get-Sequence -Map -Expression $Double -Sequence $IntArray
    .EXAMPLE
        Get-Sequence -Reduce -Expression $Sum -Sequence $IntArray
    .EXAMPLE
        Get-Sequence -Reduce $Product $IntArray
    .EXAMPLE
        Get-Sequence -Filter -Expression $IsEven -Sequence $IntArray
    .NOTES
        Matt Graeber is responsible for the guts of this code.

    .LINK
        http://www.powershellmagazine.com/2013/12/23/simplifying-data-manipulation-in-powershell-with-lambda-functions/
  #>
    [CmdletBinding(DefaultParameterSetName='None')]
    Param
    (
        # Applies a function to each element of a sequence. 
        [Parameter(Mandatory, Position=0, ParameterSetName='Map Sequence')]
        [switch]
        $Map,

        # Applies a function with two arguments cumulatively to a sequence of objects, ‘reducing’ the dataset to a single object.
        [Parameter(Mandatory, Position=0, ParameterSetName='Reduce Sequence')]
        [switch]
        $Reduce,

        # Returns a subset of objects from a sequence when a function evaluates to true.
        [Parameter(Mandatory, Position=0, ParameterSetName='Filter Sequence')]
        [switch]
        $Filter,

        # A script block with a ‘param’ declaration.
        [Parameter(Mandatory, Position=1)]
        [scriptblock]
        $Expression,
 
        # A dataset (An array of anything depending upon the given Expression.)
        [Parameter(Mandatory, Position=2)]
        [ValidateNotNullOrEmpty()]
        [object[]]
        $Sequence
    )

    Begin
    {
        Set-Variable -Option      Constant `
                     -Name        PARAMETER_ERROR `
                     -Value       "Incorrect number of parameters in Expression." `
                     -Description "The Expression ([scriptblock]) specified the wrong number of parameters."

        Set-Variable -Option      Constant `
                     -Name        FUNCTIONS_ERROR `
                     -Value       "The Map, Reduce or Filter switch was not specified." `
                     -Description "The sub-function/switch (Map, Reduce or Filter) was not specified."
    }
    Process
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'Map Sequence'
            {
                if ($Expression.Ast.ParamBlock.Parameters.Count -eq 1)
                {
                    $Sequence | ForEach-Object { &$Expression $_ }
                }
                else
                {
                    throw $PARAMETER_ERROR
                }
            }
            'Reduce Sequence'
            {
                if ($Expression.Ast.ParamBlock.Parameters.Count -eq 2)
                {
                    $accumulatedValue = $Sequence[0]

                    if ($Sequence.Length -gt 1)
                    {
                        $Sequence[1..($Sequence.Length - 1)] | ForEach-Object {
                            $accumulatedValue = &$Expression $accumulatedValue $_
                        }
                    }
 
                    $accumulatedValue
                }
                else
                {
                    throw $PARAMETER_ERROR
                }
            }
            'Filter Sequence'
            {
                if ($Expression.Ast.ParamBlock.Parameters.Count -eq 1)
                {
                    $Sequence | Where-Object { &$Expression $_ -eq $true }
                }
                else
                {
                    throw $PARAMETER_ERROR
                }
            }
            'Default'
            {
                throw $FUNCTIONS_ERROR
            }
        }
    }
    End
    {
    }
}