On Sat, 07 Nov 2009, Fernando Athayde wrote:

Hi,

> ASORT(::aArrayResumo, {|a,b| str(a[1],11)+str(a[3],11)+dtoc(a[5])+a[7] > 
> str(b[1],11)+str(b[3],11)+dtoc(b[5])+b[7] } )
> //Normal way (Slow for more than 100 registers)
> nPosicaoArray := ASCAN(::aArrayResumo, ;
>                  {|a| str(a[1],11)+str(a[3],11)+dtoc(a[5])+a[7] ==;
>                       STR( 
> ::oQueryRelatorioPrincipal:fieldGet('idgrupo_centro_custo'),11)+;
>                       
> STR(::oQueryRelatorioPrincipal:fieldGet('idcentro_custo'),11 )+;
>                       DTOC(oDB:Mysql2Date 
> (::oQueryRelatorioPrincipal:fieldGet('data_emissao') ) )+cSiglaMoeda} )
> 
> //Weighted search (Is very fast)
> nPosicaoArray := 0
> nArraySize := LEN( ::aArrayResumo )
> nJump := nArraySize - 1
> nPosition := 1
> DO WHILE .T.
>    nPosition += nJump
>    IF nPosition > nArraySize
>       nJump := 0
>       nPosition := nArraySize
>    ENDIF
>    IF str(::aArrayResumo[nPosition,1],11)+str(::aArrayResumo[nPosition,3],11);
>                +dtoc(::aArrayResumo[nPosition,5])+::aArrayResumo[nPosition,7] 
> >;
>       STR( ::oQueryRelatorioPrincipal:fieldGet('idgrupo_centro_custo'),11 );
>                 +STR( 
> ::oQueryRelatorioPrincipal:fieldGet('idcentro_custo'),11 );
>                 +DTOC(oDB:Mysql2Date 
> (::oQueryRelatorioPrincipal:fieldGet('data_emissao') ) )+cSiglaMoeda
> 
>       nPosition -= nJump
>       nJump := INT(nJump/2)
>    ENDIF
>    IF str(::aArrayResumo[nPosition,1],11)+str(::aArrayResumo[nPosition,3],11);
>             +dtoc(::aArrayResumo[nPosition,5])+::aArrayResumo[nPosition,7] == 
>       STR( ::oQueryRelatorioPrincipal:fieldGet('idgrupo_centro_custo'),11 );
>             +STR( ::oQueryRelatorioPrincipal:fieldGet('idcentro_custo'),11 );
>             +DTOC(oDB:Mysql2Date 
> (::oQueryRelatorioPrincipal:fieldGet('data_emissao') ) )+cSiglaMoeda
>       nPosicaoArray := nPosition
>       EXIT
>    ENDIF
>    IF nJump<1
>       EXIT
>    ENDIF
> ENDDO
> 
> my proposal is made a ASCANEX sending a block how parameter
> but i don´t know how to use eval and blocks

You want to use binary search for well soprted array items and
for sure it will improve the speed anyhow I suggest to use hash
arrays. If will be faster.
You can use hash array in two ways:
1. as index, i.e.:

      func arrayIndex( aValue, bOrder )
         local item
         local hValue := {=>}
         for each item in aValue
            hValue[ eval( bOrder, item ) ] := item:__enumIndex()
         next
      return hValue

   then in your code you are making:

      hIndex := arrayIndex( ::aArrayResumo, ;
                         { |a| str(a[1],11)+str(a[3],11)+dtoc(a[5])+a[7] } )

   and you can use this index to find given value position:

      cKey := STR( 
::oQueryRelatorioPrincipal:fieldGet('idgrupo_centro_custo'),11)+;
              STR(::oQueryRelatorioPrincipal:fieldGet('idcentro_custo'),11 )+;
              
DTOC(oDB:Mysql2Date(::oQueryRelatorioPrincipal:fieldGet('data_emissao') ) )+;
              cSiglaMoeda
      if cKey $ hIndex
         nPosicaoArray := hIndex[ cKey ]
         aResult := ::aArrayResumo[ nPosicaoArray ]
      endif

2. as array of values.

      func arrayToHash( aValue, bOrder )
         local item
         local hValue := {=>}
         for each item in aValue
            hValue[ eval( bOrder, item ) ] := item
         next
      return hValue

   then in your code you are making:

      hValue := arrayToHash( ::aArrayResumo, ;
                        { |a| str(a[1],11)+str(a[3],11)+dtoc(a[5])+a[7] } )

   and you can use this index to find given value:

      cKey := STR( 
::oQueryRelatorioPrincipal:fieldGet('idgrupo_centro_custo'),11)+;
              STR(::oQueryRelatorioPrincipal:fieldGet('idcentro_custo'),11 )+;
              
DTOC(oDB:Mysql2Date(::oQueryRelatorioPrincipal:fieldGet('data_emissao') ) )+;
              cSiglaMoeda
      if cKey $ hValue
         aResult := hValue[ cKey ]
      endif

Now if you look at the above the you will find that you do not have to use
arrays at all and you can replace ::aArrayResumo with ::hArrayResumo.
Just simply initialize it as empty hash array:
   ::hArrayResumo := { => }
then add all new values using code like:

   cKey := str(a[1],11)+str(a[3],11)+dtoc(a[5])+a[7]
   ::hArrayResumo[ cKey ] := a

instead of:
   aadd( ::aArrayResumo, a )

and now you can use ::hArrayResumo directly, i.e.:

      cKey := STR( 
::oQueryRelatorioPrincipal:fieldGet('idgrupo_centro_custo'),11)+;
              STR(::oQueryRelatorioPrincipal:fieldGet('idcentro_custo'),11 )+;
              
DTOC(oDB:Mysql2Date(::oQueryRelatorioPrincipal:fieldGet('data_emissao') ) )+;
              cSiglaMoeda
      if cKey $ ::hArrayResumo
         aResult := ::hArrayResumo[ cKey ]
      endif

Hash array are designed to replace normal arrays accessed by indexes
extracted with ascan() functions and are extremely fast.

best regards,
Przemek
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to