:CloseArrayGaps :CompactArray function to close gaps in arrays
Posted: 18 Sep 2023 20:06
Hello,
I needed functions to close gaps in arrays
Sometimes I need to close all gaps
Other times, I need to close only certain gaps that I have created while leaving other gaps present
So first function you call with
Call :CompactArray YourArrayName
All element gaps will be closed, array must have a defined YourArrayName.ubound value and it will adjust the ubound to the new value
Next function is :CloseArrayGaps, which you call with your array name and then indexes of gaps to close, it accepts numbers as well as anything that my function GetIndexArray can take, example
Call :CloseArrayGaps YourArrayName 4 5 9
Call :CloseArrayGaps YourArrayName 4,5,9
Call :CloseArrayGaps YourArrayName 4,5-7,9
The specified index numbers must be ascending and non repeating, as I do not sort and deduplicate them before processing
Here is the :CompactArray function
Here is :CloseArrayGaps
ToDo
Allow specifying .suffix
:CompactArray works on objects, :CloseArrayGaps does not because it does not use MoveObject
Maybe allow :CloseArrayGaps to take input of YourArrayName[X] format, in addition of arrayname indexarray
Support for arrayname.selection, to include indexarray along with the array itself in the .selection object
Here is a DEMO function called mini-DEMO
Here is the output of that function
Here is the full DEMO file which includes to more demo functions :CloseArrayGaps-DEMO :CompactArray-DEMO
As well as all the support functions for these demos
Note that :CloseArrayGaps depends on :GetIndexArray and :ClearVariablesByPrefix
While :CompactArray depends on :MoveObject and :ClearVariablesByPrefix
I needed functions to close gaps in arrays
Sometimes I need to close all gaps
Other times, I need to close only certain gaps that I have created while leaving other gaps present
So first function you call with
Call :CompactArray YourArrayName
All element gaps will be closed, array must have a defined YourArrayName.ubound value and it will adjust the ubound to the new value
Next function is :CloseArrayGaps, which you call with your array name and then indexes of gaps to close, it accepts numbers as well as anything that my function GetIndexArray can take, example
Call :CloseArrayGaps YourArrayName 4 5 9
Call :CloseArrayGaps YourArrayName 4,5,9
Call :CloseArrayGaps YourArrayName 4,5-7,9
The specified index numbers must be ascending and non repeating, as I do not sort and deduplicate them before processing
Here is the :CompactArray function
Code: Select all
::Usage Call :CompactArray InputArray
:CompactArray
set "_CompactArray_prefix=_CA
set "_CA_Input=%~1"
call set "_CA_Input_lbound=%%%_CA_Input%.lbound%%"
call set "_CA_Input_ubound=%%%_CA_Input%.ubound%%"
if "[%_CA_Input_lbound%]" EQU "[]" set "_CA_Input_lbound=0"
set /a "_CA_Index=%_CA_Input_lbound%"
set /a "_CA_Previous=%_CA_Index%-1"
if defined %_CA_Input%[%_CA_Index%] ( set /a "_CA_LastEmptyElement=%_CA_Index%+1" ) else ( set /a "_CA_LastEmptyElement=%_CA_Index%" )
:CompactArray-loop
if defined %_CA_Input%[%_CA_Index%] if %_CA_LastEmptyElement% LEQ %_CA_Previous% ( Call :MoveObject %_CA_Input%[%_CA_Index%] %_CA_Input%[%_CA_LastEmptyElement%] & set /a "_CA_LastEmptyElement+=1" )
if defined %_CA_Input%[%_CA_Index%] set /a "_CA_LastEmptyElement=%_CA_Index%+1"
set /a "_CA_Previous+=1" & set /a "_CA_Index+=1"
if %_CA_Index% LEQ %_CA_Input_ubound% GoTo :CompactArray-loop
set /a "%_CA_Input%.ubound=%_CA_LastEmptyElement%-1"
Call :ClearVariablesByPrefix %_CompactArray_prefix% _CompactArray
GoTo :EOF
Code: Select all
::Usage Call :CloseArrayGaps ArrayName IndexList1 IndexList2 IndexListN
:CloseArrayGaps
set "_CloseArrayGaps_prefix=_CAG"
set "_CAG_array=%~1" & shift
call set "_CAG_array_ubound=%%%_CAG_array%.ubound%%"
:CloseArrayGaps-arguments
if "[%~1]" NEQ "[]" ( Call :GetIndexArray _CAG_IndexList "%~1" & shift & GoTo :CloseArrayGaps-arguments )
if defined _CAG_IndexList.lbound ( set /a "_CAG_IndexList_index=%_CAG_IndexList.lbound%" ) else ( set /a "_CAG_IndexList_index=0" )
set /a "_CAG_IndexList_ubound=%_CAG_IndexList.ubound%"
call set /a "_CAG_index=%%_CAG_IndexList[%_CAG_IndexList_index%]%%"
set /a "_CAG_next_index=%_CAG_index%+1"
set /a "_CAG_IndexList_index+=1"
if %_CAG_IndexList_index% LEQ %_CAG_IndexList_ubound% ( call set /a "_CAG_next_limit=%%_CAG_IndexList[%_CAG_IndexList_index%]%%" ) else ( set /a "_CAG_next_limit=%_CAG_array_ubound%" )
GoTo :CloseArrayGaps-loop-end
:CloseArrayGaps-loop
setlocal enabledelayedexpansion
set "_CAG_localscope=true"
for /f "tokens=*" %%Z in ('echo.!%_CAG_array%[%_CAG_next_index%]!') do (
endlocal
set %_CAG_array%[%_CAG_index%]=%%Z
)
if defined _CAG_localscope endlocal
set /a "_CAG_index+=1"
set /a "_CAG_next_index+=1"
:CloseArrayGaps-loop-end
if %_CAG_next_index% LSS %_CAG_next_limit% GoTo :CloseArrayGaps-loop
if %_CAG_IndexList_index% LEQ %_CAG_IndexList_ubound% ( set /a "_CAG_IndexList_index+=1" & set /a "_CAG_next_index+=1" )
if %_CAG_IndexList_index% LEQ %_CAG_IndexList_ubound% ( call set /a "_CAG_next_limit=%%_CAG_IndexList[%_CAG_IndexList_index%]%%" )
if %_CAG_IndexList_index% LEQ %_CAG_IndexList_ubound% ( GoTo :CloseArrayGaps-loop-end ) else ( set /a "_CAG_next_limit=%_CAG_array_ubound%" )
if %_CAG_next_index% LEQ %_CAG_array_ubound% GoTo :CloseArrayGaps-loop
set /a "%_CAG_array%.ubound=%_CAG_index%-1"
Call :ClearVariablesByPrefix %_CloseArrayGaps_prefix% _CloseArrayGaps
GoTo :EOF
ToDo
Allow specifying .suffix
:CompactArray works on objects, :CloseArrayGaps does not because it does not use MoveObject
Maybe allow :CloseArrayGaps to take input of YourArrayName[X] format, in addition of arrayname indexarray
Support for arrayname.selection, to include indexarray along with the array itself in the .selection object
Here is a DEMO function called mini-DEMO
Code: Select all
:mini-DEMO
Call :ClearVariablesByPrefix myarray
set myarray[0]=element 0
set myarray[1]=element 1
set myarray[2]=element 2
set myarray[3]=element 3
set myarray[4]=element 4
REM set myarray[5]=element 5
REM set myarray[6]=element 6
REM set myarray[7]=element 7
set myarray[8]=element 8
set myarray[9]=element 9
set myarray[10]=element 10
set myarray.ubound=10
echo.&echo Printing myarray&echo.
REM call :echoarray myarray LINENUMBERS
call :echoarray myarray SHOWVARNAME
call :CloseArrayGaps myarray 5,6,7
echo.&call :echoarray myarray LINENUMBERS
Call :ClearVariablesByPrefix myarray
set myarray[0]=element 0
set myarray[1]=element 1
set myarray[2]=element 2
set myarray[3]=element 3
set myarray[4]=element 4
REM set myarray[5]=element 5
REM set myarray[6]=element 6
REM set myarray[7]=element 7
set myarray[8]=element 8
set myarray[9]=element 9
set myarray[10]=element 10
set myarray.ubound=10
echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
call :CompactArray myarray
echo.&call :echoarray myarray LINENUMBERS
Call :ClearVariablesByPrefix myarray
set myarray[0]=element 0
REM set myarray[1]=element 1
set myarray[2]=element 2
set myarray[3]=element 3
REM set myarray[4]=element 4
set myarray[5]=element 5
set myarray[6]=element 6
REM set myarray[7]=element 7
set myarray[8]=element 8
set myarray[9]=element 9
set myarray[10]=element 10
set myarray.ubound=10
echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
call :CloseArrayGaps myarray 1,4,7
echo.&call :echoarray myarray LINENUMBERS
Call :ClearVariablesByPrefix myarray
set myarray[0]=element 0
REM set myarray[1]=element 1
set myarray[2]=element 2
set myarray[3]=element 3
REM set myarray[4]=element 4
set myarray[5]=element 5
set myarray[6]=element 6
REM set myarray[7]=element 7
set myarray[8]=element 8
set myarray[9]=element 9
set myarray[10]=element 10
set myarray.ubound=10
echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
call :CompactArray myarray
echo.&call :echoarray myarray LINENUMBERS
GoTo :EOF
Code: Select all
Printing myarray
myarray[0]:element 0
myarray[1]:element 1
myarray[2]:element 2
myarray[3]:element 3
myarray[4]:element 4
myarray[5]:
myarray[6]:
myarray[7]:
myarray[8]:element 8
myarray[9]:element 9
myarray[10]:element 10
0:element 0
1:element 1
2:element 2
3:element 3
4:element 4
5:element 8
6:element 9
7:element 10
Printing myarray
0:element 0
1:element 1
2:element 2
3:element 3
4:element 4
5:
6:
7:
8:element 8
9:element 9
10:element 10
0:element 0
1:element 1
2:element 2
3:element 3
4:element 4
5:element 8
6:element 9
7:element 10
Printing myarray
0:element 0
1:
2:element 2
3:element 3
4:
5:element 5
6:element 6
7:
8:element 8
9:element 9
10:element 10
0:element 0
1:element 2
2:element 3
3:element 5
4:element 6
5:element 8
6:element 9
7:element 10
Printing myarray
0:element 0
1:
2:element 2
3:element 3
4:
5:element 5
6:element 6
7:
8:element 8
9:element 9
10:element 10
0:element 0
1:element 2
2:element 3
3:element 5
4:element 6
5:element 8
6:element 9
7:element 10
As well as all the support functions for these demos
Note that :CloseArrayGaps depends on :GetIndexArray and :ClearVariablesByPrefix
While :CompactArray depends on :MoveObject and :ClearVariablesByPrefix