Jump to content

_ArrayFilter, _ArrayMap and _ArrayReduce, by passing a function reference i.e. a function callback


guinness
 Share

Recommended Posts

Just trying out the latest version of AutoIt and thinking more functional

#include <Array.au3>

; Example
; An example of filtering, mapping and reducing arrays, using a function reference.
; This is similiar to how it would be done in the likes of JavaScript
; i.e. more functional (declarative) than procedural (imperative)

; Filter example
Local $aiFilteredBefore[] = [1, 2, 3, 50, 30, 40, 20, 30]
Local $aiFilteredAfter = _ArrayFilter($aiFilteredBefore, GtrThan30)
_ArrayDisplay($aiFilteredAfter, '_ArrayFilter::')

; Map example
Local $aiMappedBefore[] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Local $aiMappedAfter = _ArrayMap($aiMappedBefore, MultiplyByTwo)
_ArrayDisplay($aiMappedAfter, '_ArrayMap::')

; Reduce example
; Sum all values in the array
Local $aiReducedBefore[] = [1, 2, 3, 50, 30, 40, 20, 30]
ConsoleWrite('_ArrayReduce:: ' & _ArrayReduce($aiReducedBefore, SumValues) & @CRLF)

; Passing an empty array, will return the initial value; otherwise, sets @error to 4
; if no initial value is defined
Local $aEmpty[] = []
ConsoleWrite('_ArrayReduce:: ' & _ArrayReduce($aEmpty, SumValues, 0) & @CRLF)

; Array callback functions (for the examples only)

Func GtrThan30($iValue)
    Return $iValue > 30
EndFunc   ;==>GtrThan30

Func MultiplyByTwo($iValue, $iIndex, $aiArray)
    ; Notice how the function is called with the optional arguments "index" and "original array"
    ConsoleWrite('Index:: ' & $iIndex & ', Array:: ' & _ArrayToString($aiArray) & @CRLF)
    Return $iValue * 2
EndFunc   ;==>MultiplyByTwo

Func SumValues($a, $b)
    Return $a + $b
EndFunc   ;==>SumValues

; Functions

; The callback function is invoked with fn(value, [index, [array]])
Func _ArrayFilter($avArray, $hFunc)
    If Not IsArray($avArray) Then
        ; Null is more appropriate than returning the likes of -1 or an empty array
        Return SetError(1, 0, Null)
    EndIf

    If Not IsFunc($hFunc) Then
        Return SetError(2, 0, Null)
    EndIf

    Local Const $iLength = UBound($avArray)
    Local $avFiltered[$iLength]
    If $iLength = 0 Then
        Return $avFiltered
    EndIf

    Local $iIndex = 0
    For $i = 0 To $iLength - 1
        Local $bIsFiltered = __ArrayCall($hFunc, 3, $avArray[$i], $i, $avArray)
        If @error Then
            Return SetError(@error, @extended, Null)
        ElseIf $bIsFiltered Then
            $avFiltered[$iIndex] = $avArray[$i]
            $iIndex += 1
        EndIf
    Next

    ReDim $avFiltered[$iIndex]

    Return $avFiltered
EndFunc   ;==>_ArrayFilter

; The callback function is invoked with fn(value, [index, [array]])
Func _ArrayMap($avArray, $hFunc)
    If Not IsArray($avArray) Then
        ; Null is more appropriate than returning the likes of -1 or an empty array
        Return SetError(1, 0, Null)
    EndIf

    If Not IsFunc($hFunc) Then
        Return SetError(2, 0, Null)
    EndIf

    Local Const $iLength = UBound($avArray)
    Local $avMapped[$iLength]
    If $iLength = 0 Then
        Return $avMapped
    EndIf

    For $i = 0 To $iLength - 1
        $avMapped[$i] = __ArrayCall($hFunc, 3, $avArray[$i], $i, $avArray)
        If @error Then
            Return SetError(@error, @extended, Null)
        EndIf
    Next

    Return $avMapped
EndFunc   ;==>_ArrayMap

; The callback function is invoked with fn(current, value, [index, [array]])
Func _ArrayReduce($avArray, $hFunc, $vInitial = Default)
    If Not IsArray($avArray) Then
        ; Null is more appropriate than returning the likes of -1 or an empty array
        Return SetError(1, 0, Null)
    EndIf

    If Not IsFunc($hFunc) Then
        Return SetError(2, 0, Null)
    EndIf

    Local $bHasInitial = @NumParams >= 3
    Local $iLength = UBound($avArray)
    If $iLength = 0 Then
        If Not $bHasInitial Then
            Return SetError(4, 0, Null)
        EndIf

        Return $vInitial
    EndIf

    For $i = 0 To $iLength - 1
        If $bHasInitial Then
            $vInitial = __ArrayCall($hFunc, 3, $vInitial, $avArray[$i], $i, $avArray)
            If @error Then
                Return SetError(@error, @extended, Null)
            EndIf
        Else
            $bHasInitial = True
            $vInitial = $avArray[$i]
        EndIf
    Next

    Return $vInitial
EndFunc   ;==>_ArrayReduce

Func __ArrayCall($hFunc, $iError, $vArg1 = Default, $vArg2 = Default, $vArg3 = Default, $vArg4 = Default)
    Local Const $CALL_ERROR = 0xDEAD
    Local Const $CALL_EXTENDED = 0xBEEF

    Local $vRet = Call($hFunc, $vArg1)
    If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then
        $vRet = Call($hFunc, $vArg1, $vArg2)
        If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then
            $vRet = Call($hFunc, $vArg1, $vArg2, $vArg3)
            If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then
                $vRet = Call($hFunc, $vArg1, $vArg2, $vArg3, $vArg4)
                If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then
                    ; The function exists, but there is no appropriate function signature
                    Return SetError($iError, 0, Null)
                EndIf
            EndIf
        EndIf
    EndIf

    Return SetError(@error, @extended, $vRet)
EndFunc   ;==>__ArrayCall

 

Edited by guinness

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

I have updated the first post with:

  • Added _ArrayMap()
  • Callback functions now provide also the original array (similar to JavaScript)
  • Tidied code based on the style guide
  • Fixed bug in _ArrayFilter(), where the filtered array caused an "out of bounds" error

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...