supersonic Posted July 1, 2009 Share Posted July 1, 2009 (edited) Hi! Is there already a build-in function to remove empty rows in a 2D array? _ArrayUnique wouldn't help, because it's only for 1D arrays. Sure, i could write an UDF like this: #include <Array.au3> Dim $aTmp[5][5] = [[0, 1], [2, 3], ["", ""], ["", ""], [4, 5]] _ArrayDisplay($aTmp, "$aTmp_BEFORE") _Array2DDeleteEmptyRows($aTmp) _ArrayDisplay($aTmp, "$aTmp_AFTER") Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True For $i = UBound($iArray, 2) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 1) - 1 Step 1 If StringCompare($iArray[$i][$j], "", 0) <> 0 Then $vEmpty = False EndIf Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next EndFunc But when targeting rather huge arrays (> 1000) this UDF will be slow. Any ideas? Greets, -supersonic. Edited July 1, 2009 by supersonic Link to comment Share on other sites More sharing options...
supersonic Posted July 1, 2009 Author Share Posted July 1, 2009 I updated the script; maybe someone could produce fast code? Hi! Is there already a build-in function to remove empty rows in a 2D array? _ArrayUnique wouldn't help, because it's only for 1D arrays. Sure, i could write an UDF like this: #include <Array.au3> Dim $aTmp[5][5] = [[0, 1], [2, 3], ["", ""], ["", ""], [4, 5]] _ArrayDisplay($aTmp, "$aTmp_BEFORE") _Array2DDeleteEmptyRows($aTmp) _ArrayDisplay($aTmp, "$aTmp_AFTER") Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True For $i = UBound($iArray, 2) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 1) - 1 Step 1 If StringCompare($iArray[$i][$j], "", 0) <> 0 Then $vEmpty = False EndIf Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next EndFunc But when targeting rather huge arrays (> 1000) this UDF will be slow. Any ideas? Greets, -supersonic. Link to comment Share on other sites More sharing options...
weaponx Posted July 1, 2009 Share Posted July 1, 2009 Why are using StringCompare instead of just checking if the element equals "" ? Link to comment Share on other sites More sharing options...
supersonic Posted July 1, 2009 Author Share Posted July 1, 2009 Why are using StringCompare instead of just checking if the element equals "" ? You're right, I've changed the UDF: Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True If IsArray($iArray) = 1 And UBound($iArray, 2) - 1 > -1 Then For $i = UBound($iArray, 2) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 1) - 1 Step 1 If $iArray[$i][$j] <> "" Then $vEmpty = False Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next Else SetError(1, 0, 0) EndIf EndFunc But it's still slow... Link to comment Share on other sites More sharing options...
weaponx Posted July 1, 2009 Share Posted July 1, 2009 (edited) Try this. Yours took 486 ms and I got it down to 30 ms. expandcollapse popup#include <Array.au3> Dim $aTmp[1000][2] ;Fill array with junk For $X = 0 to 999 ;Insert empty element every 10 nodes, fill the rest with junk If Mod($X,10) = 0 Then $aTmp[$X][0] = "" $aTmp[$X][1] = "" Else $aTmp[$X][0] = "ebgrhrrtbnwrbnwfg" $aTmp[$X][1] = "bwefwergethcbrtgh" EndIf Next _ArrayDisplay($aTmp, "$aTmp_BEFORE") $T1 = TimerInit() ;_Array2DDeleteEmptyRows($aTmp) $aTmp = _DeleteEmptyRows($aTmp) ConsoleWrite("T1: " & TimerDiff($T1) & @CRLF) _ArrayDisplay($aTmp, "$aTmp_AFTER") ;486 ms Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True For $i = UBound($iArray) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 2)-1 Step 1 If $iArray[$i][$j] <> "" Then $vEmpty = False EndIf Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next EndFunc ;30 ms Func _DeleteEmptyRows($aArray) Local $Rows = Ubound($aArray,1) Local $Cols = Ubound($aArray,2) Local $aTemp[$Rows][$Cols] Local $not_empty Local $Count = 0 ;Loop through rows For $Y = 0 to $Rows - 1 $not_empty = 0 ;Loop through columns For $X = 0 to $Cols - 1 ;Copy all columns to temp array even if they are all empty $aTemp[$Count][$X] = $aArray[$Y][$X] ;If even one column contains data, make sure it doesn't get deleted If $aArray[$Y][$X] <> "" Then $not_empty = BitOr($not_empty, 1) Next ;If the row has any data, increment, else keep overwriting last row until it contains something If $not_empty Then $Count += 1 Next Redim $aTemp[$Count][$Cols] Return $aTemp EndFunc Edited July 1, 2009 by weaponx AnonymousX 1 Link to comment Share on other sites More sharing options...
supersonic Posted July 1, 2009 Author Share Posted July 1, 2009 Thanks for your help! Maybe UBound() in the second For-loop slows down my UDF. Try this. Yours took 486 ms and I got it down to 30 ms. expandcollapse popup#include <Array.au3> Dim $aTmp[1000][2] ;Fill array with junk For $X = 0 to 999 ;Insert empty element every 10 nodes, fill the rest with junk If Mod($X,10) = 0 Then $aTmp[$X][0] = "" $aTmp[$X][1] = "" Else $aTmp[$X][0] = "ebgrhrrtbnwrbnwfg" $aTmp[$X][1] = "bwefwergethcbrtgh" EndIf Next _ArrayDisplay($aTmp, "$aTmp_BEFORE") $T1 = TimerInit() ;_Array2DDeleteEmptyRows($aTmp) $aTmp = _DeleteEmptyRows($aTmp) ConsoleWrite("T1: " & TimerDiff($T1) & @CRLF) _ArrayDisplay($aTmp, "$aTmp_AFTER") ;486 ms Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True For $i = UBound($iArray) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 2)-1 Step 1 If $iArray[$i][$j] <> "" Then $vEmpty = False EndIf Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next EndFunc ;30 ms Func _DeleteEmptyRows($aArray) Local $Rows = Ubound($aArray,1) Local $Cols = Ubound($aArray,2) Local $aTemp[$Rows][$Cols] Local $not_empty Local $Count = 0 ;Loop through rows For $Y = 0 to $Rows - 1 $not_empty = 0 ;Loop through columns For $X = 0 to $Cols - 1 ;Copy all columns to temp array even if they are all empty $aTemp[$Count][$X] = $aArray[$Y][$X] ;If even one column contains data, make sure it doesn't get deleted If $aArray[$Y][$X] <> "" Then $not_empty = BitOr($not_empty, 1) Next ;If the row has any data, increment, else keep overwriting last row until it contains something If $not_empty Then $Count += 1 Next Redim $aTemp[$Count][$Cols] Return $aTemp EndFunc Link to comment Share on other sites More sharing options...
weaponx Posted July 1, 2009 Share Posted July 1, 2009 Thanks for your help! Maybe UBound() in the second For-loop slows down my UDF.No. _ArrayDelete is the slow part. AnonymousX 1 Link to comment Share on other sites More sharing options...
wolf9228 Posted July 1, 2009 Share Posted July 1, 2009 (edited) Hi! Is there already a build-in function to remove empty rows in a 2D array? _ArrayUnique wouldn't help, because it's only for 1D arrays. Sure, i could write an UDF like this: #include <Array.au3> Dim $aTmp[5][5] = [[0, 1], [2, 3], ["", ""], ["", ""], [4, 5]] _ArrayDisplay($aTmp, "$aTmp_BEFORE") _Array2DDeleteEmptyRows($aTmp) _ArrayDisplay($aTmp, "$aTmp_AFTER") Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True For $i = UBound($iArray, 2) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 1) - 1 Step 1 If StringCompare($iArray[$i][$j], "", 0) <> 0 Then $vEmpty = False EndIf Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next EndFunc Sorry there is an error in this code, I reform This code right #include <Array.au3> Dim $aTmp[5][5] = [[0, 1], [2, 3], ["", ""], ["", ""], [4, 5]] _ArrayDisplay($aTmp, "$aTmp_BEFORE") $iArrayOut = _Array2DDeleteEmptyRows($aTmp) _ArrayDisplay($iArrayOut, "$aTmp_AFTER") Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = False $cols = UBound($iArray, 2) Local $iArrayOut[1][$cols] , $A = 0 For $i = 0 To (UBound($iArray, 1) - 1) Step 1 if $vEmpty = True Then $A += 1 $vEmpty = False For $j = 0 To (UBound($iArray, 2) - 1) Step 1 If StringCompare($iArray[$i][$j], "", 0) <> 0 Then ReDim $iArrayOut[$A + 1][$cols] $iArrayOut[$A][$j] = $iArray[$i][$j] $vEmpty = True EndIf Next Next Return $iArrayOut EndFunc Edited July 1, 2009 by wolf9228 صرح السماء كان هنا Link to comment Share on other sites More sharing options...
weaponx Posted July 1, 2009 Share Posted July 1, 2009 #include <Array.au3> Dim $aTmp[5][5] = [[0, 1], [2, 3], ["", ""], ["", ""], [4, 5]] _ArrayDisplay($aTmp, "$aTmp_BEFORE") _Array2DDeleteEmptyRows($aTmp) _ArrayDisplay($aTmp, "$aTmp_AFTER") MsgBox(0,"",$aTmp[0][0]) Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = False $cols = UBound($iArray, 2) Local $iArrayOut[1][$cols] , $A = 0 For $i = 0 To (UBound($iArray, 1) - 1) Step 1 if $vEmpty = True Then $A += 1 $vEmpty = False For $j = 0 To (UBound($iArray, 2) - 1) Step 1 If StringCompare($iArray[$i][$j], "", 0) <> 0 Then ReDim $iArrayOut[$A + 1][$cols] $iArrayOut[$A][$j] = $iArray[$i][$j] $vEmpty = True EndIf Next Next $iArray = $iArrayOut EndFunc That took longer than the one the OP posted originally! 1740 ms AnonymousX 1 Link to comment Share on other sites More sharing options...
AnonymousX Posted February 12, 2017 Share Posted February 12, 2017 On 7/1/2009 at 10:35 AM, weaponx said: Try this. Yours took 486 ms and I got it down to 30 ms. expandcollapse popup#include <Array.au3> Dim $aTmp[1000][2] ;Fill array with junk For $X = 0 to 999 ;Insert empty element every 10 nodes, fill the rest with junk If Mod($X,10) = 0 Then $aTmp[$X][0] = "" $aTmp[$X][1] = "" Else $aTmp[$X][0] = "ebgrhrrtbnwrbnwfg" $aTmp[$X][1] = "bwefwergethcbrtgh" EndIf Next _ArrayDisplay($aTmp, "$aTmp_BEFORE") $T1 = TimerInit() ;_Array2DDeleteEmptyRows($aTmp) $aTmp = _DeleteEmptyRows($aTmp) ConsoleWrite("T1: " & TimerDiff($T1) & @CRLF) _ArrayDisplay($aTmp, "$aTmp_AFTER") ;486 ms Func _Array2DDeleteEmptyRows(ByRef $iArray) Local $vEmpty = True For $i = UBound($iArray) - 1 To 0 Step -1 For $j = 0 To UBound($iArray, 2)-1 Step 1 If $iArray[$i][$j] <> "" Then $vEmpty = False EndIf Next If $vEmpty = True Then _ArrayDelete($iArray, $i) $vEmpty = True Next EndFunc ;30 ms Func _DeleteEmptyRows($aArray) Local $Rows = Ubound($aArray,1) Local $Cols = Ubound($aArray,2) Local $aTemp[$Rows][$Cols] Local $not_empty Local $Count = 0 ;Loop through rows For $Y = 0 to $Rows - 1 $not_empty = 0 ;Loop through columns For $X = 0 to $Cols - 1 ;Copy all columns to temp array even if they are all empty $aTemp[$Count][$X] = $aArray[$Y][$X] ;If even one column contains data, make sure it doesn't get deleted If $aArray[$Y][$X] <> "" Then $not_empty = BitOr($not_empty, 1) Next ;If the row has any data, increment, else keep overwriting last row until it contains something If $not_empty Then $Count += 1 Next Redim $aTemp[$Count][$Cols] Return $aTemp EndFunc Thanks weaponx, Still helping folks 8 years after posted! weaponx 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now