I need to use array longer than 4096 elements (multidimensional if possible), and it is verry important to be used in LISTBOX.
Some sugestions ?[/b]
ARRAY over 4096 elements
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
- Enrico Maria Giordano
- Posts: 7355
- Joined: Thu Oct 06, 2005 8:17 pm
- Location: Roma - Italia
- Contact:
You can use a TWBrowse and calculate the correct position of the item to show for each index. For example (not tested):
EMG
Code: Select all
FUNCTION GETITEM( aArray, i )
IF i < 4096; RETURN aArray[ i ]; ENDIF
RETURN aArray[ 4096, i - 4095 ]
Re: ARRAY over 4096 elements
Firts, Antonio is right.avista wrote:I need to use array longer than 4096 elements (multidimensional if possible), and it is verry important to be used in LISTBOX.
Some sugestions ?[/b]
Second, try something like this with your code:
ArPrgElem[6] = TArray():New( your length array )
@ 1,1 LISTBOX ArPrgElem[3] ;
FIELDS "" ;
UPDATE ;
OF IdeArra4[5][NumPrg][1] ;
ON LEFT DBLCLICK TeclaFWD( VK_RETURN, nFlags, IdeArra)
// ArPrgElem[6] es el objeto de las array de arrays
//
ArPrgElem[3]:nAt = 1
ArPrgElem[3]:bLine = { || { ArPrgElem[6]:xGet(ArPrgElem[3]:nAt) } }
ArPrgElem[3]:bGoTop = { || ArPrgElem[3]:nAt := 1 }
ArPrgElem[3]:bGoBottom = { || ArPrgElem[3]:nAt := Eval( ArPrgElem[3]:bLogicLen ) }
ArPrgElem[3]:bSkip = { | nWant, nOld | nOld := ArPrgElem[3]:nAt, ArPrgElem[3]:nAt += nWant, ;
ArPrgElem[3]:nAt := Max( 1, Min( ArPrgElem[3]:nAt, ;
Eval(ArPrgElem[3]:bLogicLen) ) ), ArPrgElem[3]:nAt - nOld }
ArPrgElem[3]:bLogicLen = { || ArPrgElem[6]:nIndMax }
ArPrgElem[3]:cAlias = "ARRAY"
ArPrgElem[3]:GoTop()
ArPrgElem[3]:nClrText := {|| ColorBloqueo( ArPrgElem[6]:xGet(ArPrgElem[3]:nAt) )}
ArPrgElem[3]:bRClicked := { |nRow,nCol,nKeyFlags| PasaMenu(nRow, nCol, nKeyFlags, IdeArra ) }
ArPrgElem[3]:nLineStyle := 0
...
The class TARRAY:
*****************************************************************************
********************** Funciones £tiles s¢lo en FiveWin *********************
********************** 66¦ parte ********************************************
/* A tener en cuenta:
-Se trata de una matriz de 4096 * 4096 elementos.
-Se van a¤adiendo o borrando ROW's de 4096 a la vez y en esos
casos de realiza un RESIZE() de la matriz.
Se trata de un clase muy interesante a la hora de tratar array's de
grandes dimensiones (superiores a 4096 elementos).
*/
#include "FiveWin.ch"
#define CR Chr( 13 )
/*
{ { ::a2[ 1, 1 ], ::a2[ 1, 2 ], ..., ::a2[ 1, Len( ::a2[ 2 ] ) ] }, ;
{ ::a2[ 2, 1 ], ::a2[ 2, 2 ], ..., ::a2[ 2, Len( ::a2[ 2 ] ) ] }, ;
.......
{ ::a2[ 4096, 1 ], ::a2[ 4096, 2 ], ..., ::a2[ 4096, Len( ::a2[ 2 ] ) ] } ;
}
*/
/*
Con oArray:nIndMax = 500000 .-
Para nI = 245741, se produce un "Clipper internal error":
"Error no recuperable 332:
Desbordamiento de la memoria para matrices/cadenas"
He comprobado que funciona con oArray:nIndMax = 300000 .-
*/
CLASS TArray
DATA a2
DATA nIndMax, nIndRow, nIndCol
METHOD New( nIndMax ) CONSTRUCTOR // 0 <= nIndMax <= 4096^2
METHOD End() INLINE ::a2 := nil, ;
Memory( -1 )
METHOD xSet( nInd, xValor )
METHOD xGet( nInd )
METHOD uAdd( xValor ) //incluye resizing
METHOD uIns( nInd, xValor ) //incluye resizing
METHOD uDel( nInd ) //incluye resizing
METHOD uIncrSize() //m‚todo auxiliar
METHOD uDecrSize() //m‚todo auxiliar
ENDCLASS
METHOD New( nIndMax ) CLASS TArray
If nIndMax < 0 .or. nIndMax > 16777216
/*MsgStop( "Clase TArray()" + CR + ;
"nIndMax =" + Str( nIndMax ) + CR + ;
OemToAnsi( "Indice máximo fuera de rango." ),;
"0 <= nIndMax <= 4096^2 (16777216)" ;
)*/
MsgStop( "Clase TArray()" + CR + ;
"nIndMax =" + Str( nIndMax ) + CR + ;
"Indice máximo fuera de rango.", ;
"0 <= nIndMax <= 4096^2 (16777216)" ;
)
End
::nIndMax := nIndMax
::nIndRow := 4096
If ::nIndMax > 4096
::nIndCol := 1 + Int( ::nIndMax / 4096 ) // ::nIndCol >= 2
Else
::nIndCol := 1
End
::a2 := Array( ::nIndRow, ::nIndCol )
Memory( -1 )
RETURN Self
METHOD xSet( nInd, xValor ) CLASS TArray
*No lo pongo, para no retardar...
*If nInd < 1 .or. nInd > ::nIndMax
* MsgStop( "Clase TArray()" + CR + ;
* "::xSet( nInd, xValor )", ;
* "Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
* )
*End
::nIndCol := Int( nInd / 4096 ) // ::nIndCol >= 0
::nIndRow := nInd - ::nIndCol * 4096 // ::nIndRow >= 0
If ::nIndRow = 0
*( ::nIndCol > 0 )
::nIndRow := 4096
Else
::nIndCol++
End
::a2[ ::nIndRow, ::nIndCol ] := xValor
RETURN xValor
METHOD xGet( nInd ) CLASS TArray
*No lo pongo, para no retardar...
*If nInd < 1 .or. nInd > ::nIndMax
* MsgStop( "Clase TArray()" + CR + ;
* "::xGet( nInd )", ;
* "Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
* )
*End
::nIndCol := Int( nInd / 4096 ) // ::nIndCol >= 0
::nIndRow := nInd - ::nIndCol * 4096 // ::nIndRow >= 0
If ::nIndRow = 0
*( ::nIndCol > 0 )
::nIndRow := 4096
Else
::nIndCol++
End
RETURN ::a2[ ::nIndRow, ::nIndCol ]
METHOD uIncrSize() CLASS TArray
local nIndCol, nI
If ::nIndMax > 4096
nIndCol := 1 + Int( ::nIndMax / 4096 ) // nIndCol >= 2
Else
nIndCol := 1
End
::nIndMax++ ///////
::nIndRow := 4096
If ::nIndMax > 4096
::nIndCol := 1 + Int( ::nIndMax / 4096 ) // ::nIndCol >= 2
Else
::nIndCol := 1
End
If nIndCol != ::nIndCol
*Resizeado de las columnas.-
For nI := 1 To 4096
aSize( ::a2[ nI ], ::nIndCol )
Next
Memory( -1 )
End
SysRefresh() //necesario para que funcione la pr¢xima ejecuci¢n
// de funciones del tipo Msg...()
RETURN nil
METHOD uDecrSize() CLASS TArray
local nIndCol, nI
IF ::nIndMax = 1
::nIndMax-- // ::nIndMax := 0
::nIndRow := 4096
::nIndCol := 1
::a2 := Array( 4096, 1 )
Memory( -1 )
ELSE
If ::nIndMax > 4096
nIndCol := 1 + Int( ::nIndMax / 4096 ) // nIndCol >= 2
Else
nIndCol := 1
End
::nIndMax-- ///////
::nIndRow := 4096
If ::nIndMax > 4096
::nIndCol := 1 + Int( ::nIndMax / 4096 ) // ::nIndCol >= 2
Else
::nIndCol := 1
End
If nIndCol != ::nIndCol
*Resizeado de las columnas.-
For nI := 1 To 4096
aSize( ::a2[ nI ], ::nIndCol )
Next
Memory( -1 )
End
END
SysRefresh() //necesario para que funcione la pr¢xima ejecuci¢n
// de funciones del tipo Msg...()
RETURN nil
METHOD uAdd( xValor ) CLASS TArray
::uIncrSize()
::xSet( ::nIndMax, xValor )
RETURN nil
METHOD uIns( nInd, xValor ) CLASS TArray
local x
local nI
IF ::nIndMax = 0
::uIncrSize()
nInd := 1 //"pasamos de" lo que valga nInd
ELSE
If nInd > ::nIndMax
MsgStop( "Clase TArray()" + CR + ;
"::uIns( nInd, xValor )", ;
"Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
)
End
::uIncrSize()
*Desplazamiento hacia abajo.-
For nI := ::nIndMax To nInd + 1 Step -1
x := ::xGet( nI - 1 )
::xSet( nI, x )
Next
END
::xSet( nInd, xValor )
RETURN nil
METHOD uDel( nInd ) CLASS TArray
local x
local nI
IF ::nIndMax = 0
MsgStop( "Clase TArray()" + CR + ;
"Intento de borrar siendo ::nIndMax = 0",;
"::uDel( " + LTrim( Str( nInd ) ) + " )" ;
)
ELSE
If nInd > ::nIndMax
MsgStop( "Clase TArray()" + CR +;
"::uDel( nInd )", ;
"Indice fuera de rango: nInd = " + LTrim( Str( nInd ) ) ;
)
End
If ::nIndMax > 1 //de lo contrario, ::nIndMax = 1
if nInd < ::nIndMax //de lo contrario, nInd = ::nIndMax
*Desplazamiento hacia arriba.-
For nI := nInd To ::nIndMax - 1
x := ::xGet( nI + 1 )
::xSet( nI, x )
Next
end
End
*(Despreciamos el actual elemento ::nIndMax -‚simo)
::uDecrSize()
END
RETURN nil
Regards
Carlos G.
Note: Que alguién le traduzca mi mal ingles.
I solved the problem thanaks to your sugestions ....
not using the classes but this working great.
Best regards
p.s
Here is the program
=============
#include "FiveWin.ch"
static oWnd
//----------------------------------------------------------------------------//
function Main()
LOCAL oDlg
// Put in aSample array 40963
aSample={}
for i=1 to 10
aSampleTemp = {}
for j=1 to 4096
aadd(aSampleTemp,str(j))
next
aadd(aSample,aSampleTemp)
next
aadd(aSample,{"1","2","3"})
DEFINE DIALOG oDlg FROM 0, 0 TO 500,300 PIXEL ;
TITLE "Big Array"
// aSample = {{"",""}}
@ 35, 5 LISTBOX oList FIELDS "" UPDATE OF oDlg SIZE 130,200 PIXEL
oList:nAt = 1
oList:bLine = { || { MyArrItem(aSample,oList:nAt) } }
oList:bGoTop = { || oList:nAt := 1 }
oList:bGoBottom = { || oList:nAt := Eval( oList:bLogicLen ) }
oList:bSkip = { | nWant, nOld | nOld := oList:nAt, oList:nAt += nWant, ;
oList:nAt := Max( 1, Min( oList:nAt, ;
Eval(oList:bLogicLen) ) ), oList:nAt - nOld }
oList:bLogicLen = { || MyArrLen(aSample) } // len(aSample) }
oList:cAlias = "ARRAY"
oList:GoTop()
ACTIVATE DIALOG oDlg CENTERED
return NIL
//--------------------------------------------------//
FUNCTION MyArrItem( aArray, nPozicija )
nRow = INT(nPozicija/4096) + 1
nCol = nPozicija - (nRow - 1) * 4096
IF nCol=0
nRow = nRow -1
nCol=4096
ENDIF
RETURN aArray[nRow, nCol]
//--------------------------------------------------//
FUNCTION MyArrLen( aArray )
nLen = ( LEN(aArray) -1 ) * 4096
nLen = nLen + LEN(aArray[LEN(aArray)])
RETURN nLen
not using the classes but this working great.
Best regards
p.s
Here is the program
=============
#include "FiveWin.ch"
static oWnd
//----------------------------------------------------------------------------//
function Main()
LOCAL oDlg
// Put in aSample array 40963
aSample={}
for i=1 to 10
aSampleTemp = {}
for j=1 to 4096
aadd(aSampleTemp,str(j))
next
aadd(aSample,aSampleTemp)
next
aadd(aSample,{"1","2","3"})
DEFINE DIALOG oDlg FROM 0, 0 TO 500,300 PIXEL ;
TITLE "Big Array"
// aSample = {{"",""}}
@ 35, 5 LISTBOX oList FIELDS "" UPDATE OF oDlg SIZE 130,200 PIXEL
oList:nAt = 1
oList:bLine = { || { MyArrItem(aSample,oList:nAt) } }
oList:bGoTop = { || oList:nAt := 1 }
oList:bGoBottom = { || oList:nAt := Eval( oList:bLogicLen ) }
oList:bSkip = { | nWant, nOld | nOld := oList:nAt, oList:nAt += nWant, ;
oList:nAt := Max( 1, Min( oList:nAt, ;
Eval(oList:bLogicLen) ) ), oList:nAt - nOld }
oList:bLogicLen = { || MyArrLen(aSample) } // len(aSample) }
oList:cAlias = "ARRAY"
oList:GoTop()
ACTIVATE DIALOG oDlg CENTERED
return NIL
//--------------------------------------------------//
FUNCTION MyArrItem( aArray, nPozicija )
nRow = INT(nPozicija/4096) + 1
nCol = nPozicija - (nRow - 1) * 4096
IF nCol=0
nRow = nRow -1
nCol=4096
ENDIF
RETURN aArray[nRow, nCol]
//--------------------------------------------------//
FUNCTION MyArrLen( aArray )
nLen = ( LEN(aArray) -1 ) * 4096
nLen = nLen + LEN(aArray[LEN(aArray)])
RETURN nLen
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Better sample ...
If someone have better solution about sorting please reply
Best regards,
Pande.
Program ...
//---------------------------------//
#include "FiveWin.ch"
static oWnd
//----------------------------------------------------------------------------//
function Main()
LOCAL oDlg
LOCAL oBtn
// Put in aSample array 12291 elements
aSample={}
for i=1 to 3
aSampleTemp = {}
for j=4096 to 1 step -1
aadd(aSampleTemp,str(j))
next
aadd(aSample,aSampleTemp)
next
aadd(aSample,{str(1),str(2),str(3)})
DEFINE DIALOG oDlg FROM 0, 0 TO 500,300 PIXEL ;
TITLE "Big Array"
@ 35, 5 LISTBOX oList FIELDS "" UPDATE OF oDlg SIZE 130,200 PIXEL
oList:nAt = 1
oList:bLine = { || { MyArrItem(aSample,oList:nAt) } }
oList:bGoTop = { || oList:nAt := 1 }
oList:bGoBottom = { || oList:nAt := Eval( oList:bLogicLen ) }
oList:bSkip = { | nWant, nOld | nOld := oList:nAt, oList:nAt += nWant, ;
oList:nAt := Max( 1, Min( oList:nAt, ;
Eval(oList:bLogicLen) ) ), oList:nAt - nOld }
oList:bLogicLen = { || MyArrLen(aSample) } // len(aSample) }
oList:cAlias = "ARRAY"
oList:GoTop()
oList:Refresh()
// Sort aSample array if need
@ 20, 5 BUTTON oBtn PROMPT "&Sort Array" OF oDlg SIZE 130,10 PIXEL ;
ACTION ( oBtn:Disable() ,;
aSample := MyArrSort( aSample ) ,;
oBtn:Enable() ,;
oList:GoTop() ,;
oList:Refresh() ;
)
ACTIVATE DIALOG oDlg CENTERED
return NIL
//--------------------------------------------------//
// cData = aArray[ nPosition ]
// solution for big array: cData = MyArrItem( aArray, nPosition )
FUNCTION MyArrItem( aArray, nPosition )
nRow = INT(nPosition/4096) + 1
nCol = nPosition - (nRow - 1) * 4096
IF nCol=0
nRow = nRow -1
nCol=4096
ENDIF
RETURN aArray[nRow, nCol]
//--------------------------------------------------//
// nLen = LEN( aArray )
// solution for big array: nLen = MyArrLen( aArray )
FUNCTION MyArrLen( aArray )
nLen = ( LEN(aArray) -1 ) * 4096
nLen = nLen + LEN(aArray[LEN(aArray)])
RETURN nLen
//--------------------------------------------------//
// AADD( aArray, cData )
// solution for big array: MyArrAdd( aArray, cData )
FUNCTION MyArrAdd( aArray, cData )
nLen = LEN(aArray)
if nLen = 0 .or. LEN( aArray[nLen] ) = 4096
aadd( aArray, {} )
nLen = nLen +1
endif
aadd( aArray[nLen], cData )
RETURN NIL
//--------------------------------------------------//
// ASORT( aArray )
// solution for big array: MyArrSort( aArray )
// May be someone know better way to sort ?
FUNCTION MyArrSort( aArray )
for i=1 to len(aArray) // Sorting ARRAY in every element
asort(aArray)
next
if len(aArray) > 1 // MERGE sorted ARRAYS in every element in one big array
aNewArray = {aArray[1]}
for i=2 to len(aArray)
aTempArr1 = aNewArray
aTempArr2 = aArray
aNewArray = {}
nBrojac1 = 1
nBrojac2 = 1
lIzlez = .f.
do while !lIzlez
cPodatok1 = MyArrItem( aTempArr1, nBrojac1 ) // Item from bigarray
cPodatok2 = aTempArr2[ nBrojac2 ] // Item from onedimensional array
if cPodatok1 <= cPodatok2
MyArrAdd( aNewArray, cPodatok1 )
nBrojac1 = nBrojac1 +1
else
MyArrAdd( aNewArray, cPodatok2 )
nBrojac2 = nBrojac2 +1
endif
if nBrojac1 > MyArrLen( aTempArr1 )
for j = nBrojac2 to LEN( aTempArr2 )
MyArrAdd( aNewArray, aTempArr2[j] )
next
lIzlez = .t.
elseif nBrojac2 > LEN( aTempArr2 )
for j = nBrojac1 to MyArrLen( aTempArr1 )
MyArrAdd( aNewArray, MyArrItem( aTempArr1, j ) )
next
lIzlez = .t.
endif
enddo
next
endif
RETURN aNewArray
If someone have better solution about sorting please reply
Best regards,
Pande.
Program ...
//---------------------------------//
#include "FiveWin.ch"
static oWnd
//----------------------------------------------------------------------------//
function Main()
LOCAL oDlg
LOCAL oBtn
// Put in aSample array 12291 elements
aSample={}
for i=1 to 3
aSampleTemp = {}
for j=4096 to 1 step -1
aadd(aSampleTemp,str(j))
next
aadd(aSample,aSampleTemp)
next
aadd(aSample,{str(1),str(2),str(3)})
DEFINE DIALOG oDlg FROM 0, 0 TO 500,300 PIXEL ;
TITLE "Big Array"
@ 35, 5 LISTBOX oList FIELDS "" UPDATE OF oDlg SIZE 130,200 PIXEL
oList:nAt = 1
oList:bLine = { || { MyArrItem(aSample,oList:nAt) } }
oList:bGoTop = { || oList:nAt := 1 }
oList:bGoBottom = { || oList:nAt := Eval( oList:bLogicLen ) }
oList:bSkip = { | nWant, nOld | nOld := oList:nAt, oList:nAt += nWant, ;
oList:nAt := Max( 1, Min( oList:nAt, ;
Eval(oList:bLogicLen) ) ), oList:nAt - nOld }
oList:bLogicLen = { || MyArrLen(aSample) } // len(aSample) }
oList:cAlias = "ARRAY"
oList:GoTop()
oList:Refresh()
// Sort aSample array if need
@ 20, 5 BUTTON oBtn PROMPT "&Sort Array" OF oDlg SIZE 130,10 PIXEL ;
ACTION ( oBtn:Disable() ,;
aSample := MyArrSort( aSample ) ,;
oBtn:Enable() ,;
oList:GoTop() ,;
oList:Refresh() ;
)
ACTIVATE DIALOG oDlg CENTERED
return NIL
//--------------------------------------------------//
// cData = aArray[ nPosition ]
// solution for big array: cData = MyArrItem( aArray, nPosition )
FUNCTION MyArrItem( aArray, nPosition )
nRow = INT(nPosition/4096) + 1
nCol = nPosition - (nRow - 1) * 4096
IF nCol=0
nRow = nRow -1
nCol=4096
ENDIF
RETURN aArray[nRow, nCol]
//--------------------------------------------------//
// nLen = LEN( aArray )
// solution for big array: nLen = MyArrLen( aArray )
FUNCTION MyArrLen( aArray )
nLen = ( LEN(aArray) -1 ) * 4096
nLen = nLen + LEN(aArray[LEN(aArray)])
RETURN nLen
//--------------------------------------------------//
// AADD( aArray, cData )
// solution for big array: MyArrAdd( aArray, cData )
FUNCTION MyArrAdd( aArray, cData )
nLen = LEN(aArray)
if nLen = 0 .or. LEN( aArray[nLen] ) = 4096
aadd( aArray, {} )
nLen = nLen +1
endif
aadd( aArray[nLen], cData )
RETURN NIL
//--------------------------------------------------//
// ASORT( aArray )
// solution for big array: MyArrSort( aArray )
// May be someone know better way to sort ?
FUNCTION MyArrSort( aArray )
for i=1 to len(aArray) // Sorting ARRAY in every element
asort(aArray)
next
if len(aArray) > 1 // MERGE sorted ARRAYS in every element in one big array
aNewArray = {aArray[1]}
for i=2 to len(aArray)
aTempArr1 = aNewArray
aTempArr2 = aArray
aNewArray = {}
nBrojac1 = 1
nBrojac2 = 1
lIzlez = .f.
do while !lIzlez
cPodatok1 = MyArrItem( aTempArr1, nBrojac1 ) // Item from bigarray
cPodatok2 = aTempArr2[ nBrojac2 ] // Item from onedimensional array
if cPodatok1 <= cPodatok2
MyArrAdd( aNewArray, cPodatok1 )
nBrojac1 = nBrojac1 +1
else
MyArrAdd( aNewArray, cPodatok2 )
nBrojac2 = nBrojac2 +1
endif
if nBrojac1 > MyArrLen( aTempArr1 )
for j = nBrojac2 to LEN( aTempArr2 )
MyArrAdd( aNewArray, aTempArr2[j] )
next
lIzlez = .t.
elseif nBrojac2 > LEN( aTempArr2 )
for j = nBrojac1 to MyArrLen( aTempArr1 )
MyArrAdd( aNewArray, MyArrItem( aTempArr1, j ) )
next
lIzlez = .t.
endif
enddo
next
endif
RETURN aNewArray