multi dimensional array sort example please

Topic Specific Tutorials and Tips.

Moderator: Rathinagiri

Post Reply
bluebird
Posts: 165
Joined: Wed Sep 28, 2016 3:55 am
DBs Used: DBF
Has thanked: 48 times
Been thanked: 7 times

multi dimensional array sort example please

Post by bluebird » Sat Mar 11, 2017 5:06 am

Would someone who has already don this coding, please supply an example.

I want to sort each sub array (9) into strings in ascending order resulting then into 9 ordered strings,
but I don't have the codeblock experience yet.

My array will be like this one:

PUBLIC aTest := {;
{ "5", "4", "1", "6", "7", "9", "8", "2", "3" }, ;
{ "0", "7", "6", "0", "0", "2", "0", "0", "0" }, ;
{ "4", "3", "9", "8", "1", "5", "7", "2", "6" }, ;
{ "4", "0", "0", "0", "5", "0", "0", "3", "0" }, ;
{ "0", "0", "0", "4", "2", "1", "0", "0", "0" }, ;
{ "0", "5", "0", "0", "8", "0", "0", "0", "7" }, ;
{ "6", "0", "0", "5", "9", "7", "0", "4", "0" }, ;
{ "0", "0", "0", "1", "0", "0", "9", "8", "0" }, ;
{ "9", "7", "1", "6", "2", "8", "5", "4", "3" } }

Then a new single dimensional array of 9 strings of sorted digits

Awaiting with anticipation

Thanks

User avatar
serge_girard
Posts: 2283
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Has thanked: 544 times
Been thanked: 115 times
Contact:

Post by serge_girard » Sat Mar 11, 2017 9:53 am

Hello Bluebird,

Try this (maybe it can be done shorter, but it works)

Code: Select all

#include "hmg.ch"


FUNCTION MAIN()

PUBLIC aTest := {;
{ "5", "4", "1", "6", "7", "9", "8", "2", "3" }, ;
{ "0", "7", "6", "0", "0", "2", "0", "0", "0" }, ;
{ "4", "3", "9", "8", "1", "5", "7", "2", "6" }, ;
{ "4", "0", "0", "0", "5", "0", "0", "3", "0" }, ;
{ "0", "0", "0", "4", "2", "1", "0", "0", "0" }, ;
{ "0", "5", "0", "0", "8", "0", "0", "0", "7" }, ;
{ "6", "0", "0", "5", "9", "7", "0", "4", "0" }, ;
{ "0", "0", "0", "1", "0", "0", "9", "8", "0" }, ;
{ "9", "7", "1", "6", "2", "8", "5", "4", "3" } }

SET PRINTER TO sort.TXT 
SET PRINTER ON 
SET CONSOLE OFF

? 'UNSORTED'
?
FOR a = 1 TO LEN(aTEST)
   FOR b = 1 TO LEN(aTEST)
      ?? aTEST [a] [b] + ' '
   NEXT 
   ?
NEXT



aTest3 := {}  // new sorted array
FOR a = 1 TO LEN(aTEST)
    
   // put array into string
   x := ''
   FOR b = 1 TO LEN(aTest) - 1
      x := x +  aTest [a] [b]  + ','
   NEXT 
   x := x +  aTest [a] [b]   
   
   // create arrya, sort it and add to result array   
   aList := HB_ATOKENS( x, ',' )
   ASORT(aList)
   AADD(aTest3, aList)
  
NEXT

? 'SORTED'
?
FOR a = 1 TO LEN(aTEST3)
   FOR b = 1 TO LEN(aTEST3)
      ?? aTEST3 [a] [b] + ' '
   NEXT 
   ?
NEXT

SET PRINTER TO  
SET PRINTER Off
SET CONSOLE On
 
 
Serge

PeteWG
Posts: 141
Joined: Sun Mar 21, 2010 5:45 pm
Has thanked: 11 times
Been thanked: 45 times

Post by PeteWG » Sat Mar 11, 2017 12:02 pm

Hi,

Not sure I did understand what exactly sorting you want,
maybe the below code is what you're looking for:

Code: Select all

PROCEDURE Main()
   MEMVAR aTest
   LOCAL aStrings := {}
   LOCAL aSub, s

   PUBLIC aTest := {;
   { "5", "4", "1", "6", "7", "9", "8", "2", "3" }, ;
   { "0", "7", "6", "0", "0", "2", "0", "0", "0" }, ;
   { "4", "3", "9", "8", "1", "5", "7", "2", "6" }, ;
   { "4", "0", "0", "0", "5", "0", "0", "3", "0" }, ;
   { "0", "0", "0", "4", "2", "1", "0", "0", "0" }, ;
   { "0", "5", "0", "0", "8", "0", "0", "0", "7" }, ;
   { "6", "0", "0", "5", "9", "7", "0", "4", "0" }, ;
   { "0", "0", "0", "1", "0", "0", "9", "8", "0" }, ;
   { "9", "7", "1", "6", "2", "8", "5", "4", "3" } }

   FOR EACH aSub IN aTest
      s := ""
      AEval( ASort( aSub ), {|e| s += e} )
      AAdd( aStrings, s )
   NEXT
   // aStrings := ASort( aStrings ) // uncomment this line if you also need aStrings sorted

   hb_Alert( aStrings )
   
   RETURN
regards,

---
Pete

bluebird
Posts: 165
Joined: Wed Sep 28, 2016 3:55 am
DBs Used: DBF
Has thanked: 48 times
Been thanked: 7 times

Post by bluebird » Sat Mar 11, 2017 6:18 pm

Thank you to Serge and PeteWG

The examples will work, I will study them carefully

Now I want to add this question, viz.

I also want to sort the same array columns and compare the result to the "alldigits" string as a test that the column data is also full and no digits are missing.
In my own muddling way I found that this line works on sorting rows i.e.

AEVAL(aTest, { | nVal, nIdx | ASort(aTest[nIdx]) }, 1, 9 )

how can I make it work on columns 1 to 9?

Thanks, great support

User avatar
serge_girard
Posts: 2283
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Has thanked: 544 times
Been thanked: 115 times
Contact:

Post by serge_girard » Sun Mar 12, 2017 7:54 am

Bluebird,

Maybe the AEVAL in a FOR/NEXT loop?

Serge

bluebird
Posts: 165
Joined: Wed Sep 28, 2016 3:55 am
DBs Used: DBF
Has thanked: 48 times
Been thanked: 7 times

Post by bluebird » Mon Mar 13, 2017 9:53 pm

Dear mentors and readers

I have had a hang up about dealing with multi dimensional arrays. Seeing how to operate row by row is OK but how do you operate (example sort) by columns when multidimensional arrays are just nested rows in Clipper .

An easy solution???
My idea now is to treat the array as a matrix. It you transpose a matrix each row becomes a column in the transposed matrix (or AKA array).Now you can process the columns in the old array because they are now rows in the transpose.

aMatix:=array(5,3) transposes to bMatrix:=array(3,5). Shouldn't matter what the element types are (numbers, strings,etc)

I am wondering if there is a way to implement an "array" transpose into a codeblock.

Thanks for putting up with my unique problems.

trmpluym
Posts: 242
Joined: Tue Jul 15, 2014 6:52 pm
Location: The Netherlands
Has thanked: 6 times
Been thanked: 21 times

Post by trmpluym » Tue Mar 14, 2017 8:06 am

Bluebird,

Did you read this article ?

https://vivaclipper.wordpress.com/2013/ ... ay-basics/

This sample is a good example to sort an array with 2 dimensions:
This example sorts a nested array using the second element of each sub-array:

aKids := { {"Mary", 14}, {"Joe", 23}, {"Art", 16} }
aSortKids := ASORT(aKids,,, { |x, y| x[2] < y[2] })
Result:

{ {“Mary”, 14}, {“Art”, 16}, {“Joe”, 23} }
Theo

Post Reply