AScan() a Multi-Dimensional Array

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

Red2
Posts: 282
Joined: Sat May 18, 2019 2:11 pm
DBs Used: Visual FoxPro, FoxPro
Location: United States of America

AScan() a Multi-Dimensional Array

Post by Red2 »

I need to AScan() a multi-dimensional array. It should be easy but I need your kind guidance.

// With a numeric 3-D array as follows:
LOCAL laPrimeCounts := { {10,1,0.1}, {100,25,0.2}, {1000,168,0.3}, {10000,1229,0.4}, {100000,9592,0.5}, ;
{1000000,78498,0.6}, {10000000,664579,0.7}, {100000000,5761455,0.8} }

// Example: My lines below return 0 (rather than the row #2):
lnColumn1_Hit := AScan( laPrimeCounts, 100 ) // Returns 0
lnColumn2_Hit := AScan( laPrimeCounts, 25 ) // Returns 0
lnColumn3_Hit := AScan( laPrimeCounts, 0.2 ) // Returns 0

QUESTION:
How can I AScan() an N-Dimension array (2-D, 3-D, or 4-D ) to identify the array row containing a value in a particular column?
I assume such a solution adapts for a character array, correct?

Thank you for your genereous help!

Red2
User avatar
serge_girard
Posts: 3420
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: AScan() a Multi-Dimensional Array

Post by serge_girard »

Red2,

Personnaly I would NOT use ASCAN...
I prefer my own little routine:

Code: Select all

FUNCTION MAIN()
/******************/
LOCAL laPrimeCounts := { ;
{10,1,0.1}, ;
{100,25,0.2}, ;
{1000,168,0.3}, ;
{10000,1229,0.4}, ;
{100000,9592,0.5}, ;
{1000000,78498,0.6}, ;
{10000000,664579,0.7}, ;
{100000000,5761455,0.8} }

SET PRINTER TO C:\test\SCAN.TXT
SET PRINTER ON 
SET CONSOLE OFF  



aSEARCH := {}
AADD(aSEARCH, 10000)    // FOUND
AADD(aSEARCH, 664579)   // FOUND
AADD(aSEARCH, 62364579) // NOT FOUND
AADD(aSEARCH, .03)      // NOT FOUND
AADD(aSEARCH, .300)     // FOUND

FOR xx :=  1 to len(aSEARCH)
   nSEARCH := aSEARCH [XX]
   FOR a := 1 to len(laPrimeCounts)
    
      FOR b := 1 to len(laPrimeCounts [a] )
         IF laPrimeCounts [a,b ] == nSEARCH
            ? 'found', laPrimeCounts [a,b ]
         ENDIF
         
      NEXT 
   NEXT
NEXT
QUIT
This works very fine and easy to expand!

Serge
There's nothing you can do that can't be done...
Red2
Posts: 282
Joined: Sat May 18, 2019 2:11 pm
DBs Used: Visual FoxPro, FoxPro
Location: United States of America

Re: AScan() a Multi-Dimensional Array

Post by Red2 »

Thank you very much Serge.

I can manually write code to iterate through an array's specific column.
I guess that what I really want to know is does the HMG syntax,
ASCAN( <aTarget>, <xSearch>, [<nStart>], [<nCount>] ) --> nStoppedAt
only support a 1-Dimensional array?

As of Visual FoxPro's version 7 one could specify the column to be scanned:
nResult = ASCAN( ArrayName, uExpression [, nStart [, nNumElems [, nColumn [, nFlags ] ] ] ] )

QUESTION:
Was column searching of a Multi-Dimensional array ever implemented in HMG or Harbour in a function?
If so I would appreciate it if the function and it's syntax would be shared.

Thanks again for all of your expert HMG guidance.
Red2
User avatar
serge_girard
Posts: 3420
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: AScan() a Multi-Dimensional Array

Post by serge_girard »

There's nothing you can do that can't be done...
Red2
Posts: 282
Joined: Sat May 18, 2019 2:11 pm
DBs Used: Visual FoxPro, FoxPro
Location: United States of America

Re: AScan() a Multi-Dimensional Array

Post by Red2 »

Thank you very much Serge for your help! I have looked at both of the URLs.
Only https://harbour.github.io/doc/harbour.html#ascan
has a Multi-Dimensional example.

I am confused. When running either the 1) the web page's interactive example or
when running the example code 2) locally on my machine the result returned (by both) is 0.

Code: Select all

#include "directry.ch"
LOCAL nStoppedAt
LOCAL aDir := hb_vfDirectory( "*.prg" )
//
nStoppedAt := AScan( aDir,,, {| aFile, nPos | HB_SYMBOL_UNUSED( nPos ), aFile[ F_NAME ] == "Main.prg" } )
msginfo( "Result:  " + NtoC( nStoppedAt )	// Returns 0
What mistakes am I making? Is something else going on?

I still have not been able to successfully run AScan() on my array locally:

Code: Select all

LOCAL laPrimeCounts := { {10,1}, {100,25}, {1000,168}, {10000,1229}, {100000,9592} ;
					,	 {1000000,78498}, {10000000,664579}, {100000000,5761455} }
lnHit := AScan( laPrimeCounts, 100, 1 )  // Returns 0
Perhaps I do not understand AScan's syntax:
nStoppedAt := AScan( <aArray>, <xSearch>, [<nStart>], [<nCount>] )
aArray: Array to be scanned.
xSearch: Expression to search for in aTarget
nStart: Beginning subscript position at which to start the search.
nCount: Number of elements to scan with aTarget.
Does nStart refer to, the column number or row number?

Thanks again. Any suggestion that help me understand would be greatly appreciated.
Red2
User avatar
serge_girard
Posts: 3420
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: AScan() a Multi-Dimensional Array

Post by serge_girard »

To be honest: I don't use ASCAN... I use my own FOR-NEXT loops! I always had a problem with ASCAN. Maybe somebody else knows right syntax/use.

Serge
There's nothing you can do that can't be done...
User avatar
AUGE_OHR
Posts: 2117
Joined: Sun Aug 25, 2019 3:12 pm
DBs Used: DBF, PostgreSQL, MySQL, SQLite
Location: Hamburg, Germany

Re: AScan() a Multi-Dimensional Array

Post by AUGE_OHR »

hi Red

search Filename in DIRECTORY Array

Code: Select all

  aDir := DIRECTORY( cPath + "*.*", "DHS" )
  nPosi := ASCAN( aDir, { | x | lower(x[ F_NAME ]) = lower(cFile) } )
sort DIRECTORY Array to have "D" on Top

Code: Select all

  // "D"irectry on Top
  ASORT( aDir,,, { | x, y | "D" $ x[ F_ATTR ] } )
  AEVAL( aDir, { | x, i | nStartAt := IF( "D" $ x[ F_ATTR ], i, nStartAt ) } )
  ASORT( aDir, 1, nStartAt, { | x, y | LOWER( x[ F_NAME ] ) < LOWER( y[ F_NAME ] ) } )
  //now sort Size
  IF ::SortOrder = LVS_SORTASCENDING
      ASORT( aDirOut, nStartAt + 1,, { | x, y | ( x[ F_SIZE ] ) < ( y[ F_SIZE ] ) } )
  ELSE
      ASORT( aDirOut, nStartAt + 1,, { | x, y | ( x[ F_SIZE ] ) > ( y[ F_SIZE ] ) } )
  ENDIF
Red2 wrote: Thu Nov 24, 2022 5:41 pm Does nStart refer to, the column number or row number?
on ROW
have fun
Jimmy
anupamgaurav22
Posts: 1
Joined: Mon May 27, 2013 3:20 pm

Re: AScan() a Multi-Dimensional Array

Post by anupamgaurav22 »

Hi Red

you can try below code -

Code: Select all

LOCAL laPrimeCounts := { {10,1,0.1} ,; 
                         {100,25,0.2},;
                         {1000,168,0.3},;
                         {10000,1229,0.4},;
                         {100000,9592,0.5},;
                         {1000000,78498,0.6},;
                         {10000000,664579,0.7},;
                         {100000000,5761455,0.8} }


? AScan( laPrimeCounts, { |arr| arr[1]==100 } )
? AScan( laPrimeCounts, { |arr| arr[2]==25 } )
? AScan( laPrimeCounts, { |arr| arr[3]==0.5 } )

Anupam
User avatar
serge_girard
Posts: 3420
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: AScan() a Multi-Dimensional Array

Post by serge_girard »

anupamgaurav22 solution is OK but.....

Code: Select all

LOCAL laPrimeCounts := { {10,1,0.1} ,; 
                         {100,25,0.2},;
                         {1000,168,0.3},;
                         {10000,1229,0.4},;
                         {100000,9592,0.5},;
                         {100000,1119592,0.5},;
                         {100000,9522222292,0.5},;
                         {1000000,78498,0.6},;
                         {10000000,664579,0.7},;
                         {100000000,5761455,0.8} }

? AScan( laPrimeCounts, { |arr| arr[1]==100 } )
? AScan( laPrimeCounts, { |arr| arr[2]==25 } )
? AScan( laPrimeCounts, { |arr| arr[3]==0.5 } )



It will only find FIRST appearance of 0.5 in this array. My LOOP construction will find every appearance.
Or is there some flag missing saying all appearances?

S
There's nothing you can do that can't be done...
Red2
Posts: 282
Joined: Sat May 18, 2019 2:11 pm
DBs Used: Visual FoxPro, FoxPro
Location: United States of America

Re: AScan() a Multi-Dimensional Array

Post by Red2 »

Hello all,

Serge's solution can identify a value in more than 1 array row. Thanks!
Jimmy's showed me interesting ways to manipulate arrays. Thanks!

Thank you anupamgaurav22! You taught me the AScan() syntax I needed for Multi-Dimensional array lookups.
This is exactly what I wanted. (Coming from a VFP background, code blocks are something I am slowly learning).

For what it is worth, this all came about from viewing the following video.
It challenged me to create, using the HMG language, the fastest Prime Number generator program I could.

"E00: Software Drag Racing: C++ vs C# vs Python - Which Will Win?"
https://www.youtube.com/watch?v=D3h62rgewZM&t=717s


There are two considerations, the most efficient algorithm and the best use of a programming language.
I may not have accomplished either but it has been a great learning experience.
Interestingly using the same .PRG my results showed Official HMG was 1.29% faster than HMG Extended.

In case anyone is interested I plan on posting my "HMG" code in a day or two (after a little cleanup).

Thanks again for everyone's help!
Red2
Post Reply