Jump to content

Array functions I'd like see added to the ARRAY UDF


sshrum
 Share

Recommended Posts

Currently, the Array UDF handles single dim'ed arrays. Here are a couple of funcs I made that handle single and 2 dimension'ed arrays:

_ArrayShuffle - takes an array Byref and shuffles the row ordering

_ArrayMerge - takes 2 similar dim'ed arrays and appends one to the other, updates the # in [0],[0][0]

_ArrayFilter - full-text or column-specific searches of single or 2 dim'ed arrays, returns back an array of row contents that match

_Array2File - dumps the array out to a file, support for user defined separators

_File2Array - loads a array file into and array, looks at line 1 for dimensions and seperator

_KeySet - think of it as WriteINI for arrays, I use this to create a master variables list

_ValueGet - think of this as ReadINI for arrays, I use this to read the master variables list

Why, you ask?

I use _KeySet to create an array of key=value pairs (like an INI file) and use _ValueGet to retrieve them. Also, this way I can parse the array for a complete list of variables that are defined. I then use _Array2File to store the values to a file so after the app quits, I can use _File2Array to reload the values back in.

_ArrayMerge is great when you are dealing with a lot of arrays that you want to bring together into one. _ArrayFilter for when you only want certain data, and _ArrayShuffle...well, for when you want to mix up the contents of an array (2-dim relations are kept...basically this means it just shuffles rows)

Not really a UDF but 95% of the work is in there. Check it out and let me know if they can be improved on:

func _Array2File($aTemp, $sFilename, $iBase=1, $sSeperator="|")
    Consolewrite("(_Array2File) ")
    $iTimer = TimerInit()
    $iRows = ubound($aTemp) - $iBase
    $iCols = ubound($aTemp,2)
    if $iCols = 0 then $iCols = 1
    ConsoleWrite("[ " & $iRows & " " & $sSeperator & " " & $iCols & " ] -> Writting '" & $sFilename & "'; ")
    $fOutput = FileOpen($sFilename, 2+8)
    FileWriteLine($fOutput, $iRows & $sSeperator & $iCols)
    if $iCols = 1 then 
        For $i = $iBase to $iRows
            FileWriteLine($fOutput, $aTemp[$i])
        next        
    Else
        For $i = $iBase to $iRows
            $sLine = ""
            for $j = 0 to ($iCols - 1)
                if $j <> 0 AND $iCols > 1 then $sLine &= $sSeperator 
                $sLine &= $aTemp[$i][$j]
            Next
            FileWriteLine($fOutput, $sLine)
        next
    EndIf
    Fileclose($fOutput)
    ConsoleWrite("complete [" & Round(TimerDiff($iTimer)/1000,2) & " secs]" & @CRLF)
    return $aTemp
EndFunc

Func _ArrayFilter($aTemp, $sSearch, $iBase=1, $iCol=-1, $iCase=2)
    Consolewrite("(_ArrayFilter) ")
    $iTimer = TimerInit()
    $iRows = ubound($aTemp) - $iBase
    if $iRows = 0 then return $aTemp
    $iCols = ubound($atemp,2)
    if $iCols = 0 then 
        Dim $aTemp2[$iRows]
        $aTemp2[0] = 0
        ConsoleWrite("[ " & $iRows & " ] ")
    Else
        Dim $aTemp2[$iRows][$iCols]
        $aTemp[0][0] = 0
        ConsoleWrite("[ " & $iRows & " x " & $iCols & " ] ")
    EndIf
    Consolewrite("-> Looking for '" & $sSearch & "' ")
    if $iCol > $iCols then 
        seterror(1)
        return $aTemp2
    EndIf
    $aSearch = StringSplit($sSearch, ",")
    $iLine = 0
    $iFlag = False
    if $iCols = 0 Then
        For $i = $iBase to $iRows
            for $k = 1 to $aSearch[0]
                if stringinstr($aTemp[$i], $aSearch[$k], $iCase) then
                    $iLine += 1
                    $aTemp2[$iLine] = $aTemp[$i]
                    ExitLoop
                endif
            next
        next        
        redim $aTemp2[$iLine+1]
        $aTemp2[0] = $iLine
    Else
        if $iCol = -1 Then
            ConsoleWrite("in all fields...")
            For $i = $iBase to $iRows
                for $j = 0 to ($iCols - 1)
                    for $k = 1 to $aSearch[0]
                        if stringinstr($aTemp[$i][$j], $aSearch[$k], $iCase) then
                            $iLine += 1
                            $iFlag = true
                            ExitLoop 2
                        endif
                    next
                Next
                if $iFlag Then
                    for $j = 0 to ($iCols - 1)
                        $aTemp2[$iLine][$j] = $aTemp[$i][$j]
                    Next
                    $iFlag = False
                EndIf
            next
        Else
            ConsoleWrite("in column " & $iCol & "...")
            For $i = $iBase to $iRows
                for $k = 1 to $aSearch[0]
                    if stringinstr($aTemp[$i][$iCol], $aSearch[$k], $iCase) then
                        $iLine += 1
                        $iFlag = true
                        ExitLoop
                    endif
                next
                if $iFlag Then
                    for $j = 0 to ($iCols - 1)
                        $aTemp2[$iLine][$j] = $aTemp[$i][$j]
                    Next
                    $iFlag = False
                EndIf
            Next
        EndIf
        redim $aTemp2[$iLine+1][$iCols]
        $aTemp2[0][0] = $iLine
    EndIf   
    ConsoleWrite($iLine & " records found; complete [" & Round(TimerDiff($iTimer)/1000,2) & " secs]" & @CRLF)
    return $aTemp2
EndFunc

func _ArrayMerge (ByRef $aTemp1, $aTemp2, $iBase=1)
    Consolewrite("(_ArrayMerge) ")
    $iTimer = TimerInit()
    $iRows1 = ubound($aTemp1) - $iBase
    $iCols1 = ubound($aTemp1,2)
    $iRows2= ubound($aTemp2) - $iBase
    $iCols2 = ubound($aTemp2,2)
    If $iCols1 <> $iCols2 then 
        seterror(1)
        Exit
    endif
    ConsoleWrite("Merging " & $iRows2 & " entries with " & $iRows1 & " entries in originating array...")
    If $iCols1 = 0 Then
        $iTotal = $aTemp1[0] + $aTemp2[0]
        redim $aTemp1[$iTotal+1]
        For $i = $aTemp1[0][0] + $iBase to $iTotal
            $aTemp1[$i] = $aTemp2[$i - ($aTemp1[0] + $iBase) + 1]
        next
        $aTemp1[0] = $iTotal
    Else
        $iTotal = $aTemp1[0][0] + $aTemp2[0][0]
        redim $aTemp1[$iTotal+1][$iCols1]
        For $i = $aTemp1[0][0] + $iBase to $iTotal
            for $j = 0 to ($iCols1 - 1)
                $aTemp1[$i][$j] = $aTemp2[$i - ($aTemp1[0][0] + $iBase) + 1][$j]
            Next
        next
        $aTemp1[0][0] = $iTotal
    EndIf
    ConsoleWrite("complete [" & Round(TimerDiff($iTimer)/1000,2) & " secs]" & @CRLF)
EndFunc

Func _ArrayShuffle(ByRef $aTemp, $iBase=1)
    Consolewrite("(_ArrayShuffle) ")
    $iTimer = TimerInit()
    $iRows = UBound($aTemp) -1
    $iCols = UBound($aTemp,2)
    if $iCols = 0 then 
        ConsoleWrite("[ " & $iRows & " ] ")
        For $i = $iBase To $iRows
            $iRandom = Random($iBase,$iRows)
            $sTemp = $aTemp[$i]
            $aTemp[$i] = $aTemp[$iRandom]
            $aTemp[$iRandom] = $sTemp
        Next
    Else
        Dim $aTemp2[1][$iCols]
        ConsoleWrite("[ " & $iRows & " x " & $iCols & " ] ")
        For $i = $iBase To $iRows - $iBase
            $iRandom = Random($iBase,$iRows)
            For $j = 0 to $iCols - 1
                $aTemp2[0][$j] = $aTemp[$i][$j]
                $aTemp[$i][$j] = $aTemp[$iRandom][$j]
                $aTemp[$iRandom][$j] = $aTemp2[0][$j]
            Next
        Next
    EndIf
    ConsoleWrite("complete [" & Round(TimerDiff($iTimer)/1000,2) & " secs]" & @CRLF)
EndFunc

Func _File2Array($sFilename)
    Consolewrite("(_File2Array) ")
    $iTimer = TimerInit()
    $iSize = round(FileGetSize($sFilename)/1024/1024,2)
    $fInput = FileOpen($sFilename,0)
    $sMatrix = FileReadLine($fInput)
    $sSeperator = StringRegExpReplace($sMatrix, "[0-9]", "")
    $aMatrix = StringSplit($sMatrix, $sSeperator)
    consolewrite("[ " & $aMatrix[1] & " x " & $aMatrix[2] & " ] -> Reading '" & $sFilename & "' (" & $iSize & " megs); ")
    if $aMatrix[2] = 1 Then
        Dim $aTemp[$aMatrix[1]+1]
        $aTemp[0]=$aMatrix[1]
    Else
        Dim $aTemp[$aMatrix[1]+1][$aMatrix[2]]
        $aTemp[0][0]=$aMatrix[1]
    EndIf
    if $aMatrix[2] = 1 Then
        For $i = 1 to $aMatrix[1]
            $aTemp[$i] = FileReadLine($fInput)
        Next        
    Else
        For $i = 1 to $aMatrix[1]
            $sLine = FileReadLine($fInput)
            $aLine = StringSplit($sLine, $sSeperator)
            for $j = 1 to $aMatrix[2]
                $aTemp[$i][$j-1] = $aLine[$j]
            Next
        Next
    EndIf
    Fileclose($fInput)
    ConsoleWrite("complete [" & Round(TimerDiff($iTimer)/1000,2) & " secs]" & @CRLF)
    return $aTemp
EndFunc

func _KeySet(Byref $aTemp, $sKey, $sValue)
    for $i = 1 to $aTemp[0][0]
        if $aTemp[$i][0] = $sKey then 
            $aTemp[$i][1] = $sValue
            Return
        EndIf
    Next
    $iNext = $aTemp[0][0]+1
    ReDim $aTemp[$iNext+1][2]
    $aTemp[0][0] = $iNext
    $aTemp[$iNext][0] = $sKey
    $aTemp[$iNext][1] = $sValue
    _arraySort($aTemp,0,1,0,2,0)
EndFunc

func _ValueGet(ByRef $aTemp, $sKey)
    for $i = 1 to $aTemp[0][0]
        if $aTemp[$i][0] = $sKey then return $aTemp[$i][1]
    Next
    return
EndFunc

- Enjoy

Edited by sshrum

Sean Shrum :: http://www.shrum.net

All my published AU3-based apps and utilities

'Make it idiot-proof, and someone will make a better idiot'

 

Link to comment
Share on other sites

  • 2 years later...

I love the features just wanted to mention I have been trying to figure out how to store an array that a helper script of mine makes into a file so that another script can grab and use that array. I tried using your array to file and file to array but for some reason its chopping out one of the items in the array..

I have an array thats looks something like : $array[1681] = blah

I stored it to a txt file and re-grabbed it and its coming back as an array with only 1680 elements instead of the 1681? Also the array I stored I had striped the $array[0] out of it that shows how many items are in the array and when I pulled the array back from the file it had that item in it again?

Love the idea, don't know if its just that I am an idiot but I can't get it to work...

Keltset

-K

Link to comment
Share on other sites

Make sure you are setting $iBase to 0 when you call the function. That way, the function knows to write the elements starting at 0. Many people use $array[0] as an index for the number of elements in the array. That is probably why the default value is set to 1.

Edited by dantay9
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...