Response: Array Class Generic Sort



Here is my attempt at providing details in response to an article by ChiliJoe called PeopleCode Array Class’ Generic Sort.

Basically, ChiliJoe is referring to a vague example in PeopleBooks that says, “For example, suppose you want to provide a more generic sort, with comparison function at the end of it.” This is in the section: “When Would You Use Application Classes?“.

The key to this example is that you have to write the sort by extending the array class. Here is an attempt at writing an example:

This is the generic interface that allows comparing any type of variable:

interface ICompare
   method compare(&a As any, &b As any) Returns number;
end-interface;

This is the class that contains the logic for doing the compare:

import SKP_EXAMPLE:ICompare;

class RecordCompare implements SKP_EXAMPLE:ICompare
   method RecordCompare();
   method setCompareByName();
   method setCompareByFieldCount();
   method compare(&a As any, &b As any) Returns number;
private
   instance number &compareType;
   Constant &constCompareByName = 1;
   Constant &constCompareByFieldCount = 2;
end-class;

method RecordCompare
   /* default to compare by name */
   &compareType = &constCompareByName;
end-method;

method setCompareByName
   &compareType = &constCompareByName;
end-method;

method setCompareByFieldCount
   &compareType = &constCompareByFieldCount;
end-method;

method compare
   /+ &a as Any, +/
   /+ &b as Any +/
   /+ Returns Number +/
   /+ Extends/implements SKP_EXAMPLE:ICompare.compare +/
   If &compareType = &constCompareByName Then;
      If &a.Name = &b.Name Then;
         Return 0;
      Else;
         If &a.Name > &b.Name Then;
            Return 1;
         Else;
            Return - 1;
         End-If;
      End-If;
   Else;
      If &compareType = &constCompareByFieldCount Then;
         If &a.FieldCount = &b.FieldCount Then;
            Return 0;
         Else;
            If &a.FieldCount > &b.FieldCount Then;
               Return 1;
            Else;
               Return - 1;
            End-If;
         End-If;
      End-If;
   End-If;
   Return 0;
end-method;

This is the class that extends the Array class and performs the custom sort using the interface above as the logic in comparing the elements (Note: the code ignores the sort direction parameter):

import SKP_EXAMPLE:ICompare;

class GenericSortArray extends Array
   method GenericSortArray(&array As array);
   method Sort(&sort_direction As string);
   property SKP_EXAMPLE:ICompare CompareClass get set;
private
   instance SKP_EXAMPLE:ICompare &compare;
end-class;

method GenericSortArray
   /+ &array as Array of Any +/
   %Super = &array;
end-method;

get CompareClass
   /+ Returns SKP_EXAMPLE:ICompare +/
   Return &compare;
end-get;

set CompareClass
   /+ &NewValue as SKP_EXAMPLE:ICompare +/
   &compare = &NewValue;
end-set;

method Sort
   /+ &sort_direction as String +/
   /+ Extends/implements Array.Sort +/
   Local number &size;
   Local number &x;
   Local any &currentElement;
   Local any &elementToMove;
   Local number &indexToMove;

   &size = %Super.Len;
   While &size > 1;
      &elementToMove = %Super.Get(1);
      &indexToMove = 1;
      For &x = 2 To &size;
         &currentElement = %Super.Get(&x);
         If &compare.compare(&elementToMove, &currentElement) > 0 Then;
            &elementToMove = &currentElement;
            &indexToMove = &x;
         End-If;
      End-For;
      /* remove the element */
      %Super.Replace(&indexToMove, 1);
      /* add the element to the end */
      %Super.Push(&elementToMove);
      /* shorten the length of the array left to sort */
      &size = &size - 1;
   End-While;
   If &size = 1 And
         %Super.Len > 1 Then;
      &elementToMove = %Super.Get(1);
      %Super.Replace(1, 1);
      %Super.Push(&elementToMove);
   End-If;
end-method;

This is Application Engine PeopleCode that demonstrates the usage of the above code:

import SKP_EXAMPLE:GenericSortArray;
import SKP_EXAMPLE:RecordCompare;

Local File &out;
Local SKP_EXAMPLE:GenericSortArray &sortArray;
Local SKP_EXAMPLE:RecordCompare &compareMethod;
Local Record &rec;

Function print_array(&ary As array);
   Local number &x;
   Local Record &currentRecord;

   For &x = 1 To &ary.Len;
      &currentRecord = &ary.Get(&x);
      &out.WriteLine("  " | &x | ": " | &currentRecord.Name | " -- " | &currentRecord.FieldCount | " fields");
   End-For;
End-Function;

/* open file for logging */

&out = GetFile("c:tempexample_output.txt", "w", "a", %FilePath_Absolute);

/* populate array */
&sortArray = create SKP_EXAMPLE:GenericSortArray(CreateArrayAny());
&rec = CreateRecord(Record.JOB);
&sortArray.Push(&rec);
&rec = CreateRecord(Record.ABSENCE_HIST);
&sortArray.Push(&rec);
&rec = CreateRecord(Record.ZBD_JOBCODE_TBL);
&sortArray.Push(&rec);
&out.WriteLine("Initial Array:");
print_array(&sortArray);

/* Sort by Name */
&out.WriteLine(" ");
&out.WriteLine("Compare By Name:");
&compareMethod = create SKP_EXAMPLE:RecordCompare();
&compareMethod.setCompareByName();
&sortArray.CompareClass = &compareMethod;
&sortArray.Sort("A");
print_array(&sortArray);

/* Sort by Field Count */
&out.WriteLine(" ");
&out.WriteLine("Compare By Field Count:");
&compareMethod = create SKP_EXAMPLE:RecordCompare();
&compareMethod.setCompareByFieldCount();
&sortArray.CompareClass = &compareMethod;
&sortArray.Sort("A");
print_array(&sortArray);

&out.Close();

Finally, here is the output:

Initial Array:
  1: JOB -- 162 fields
  2: ABSENCE_HIST -- 61 fields
  3: ZBD_JOBCODE_TBL -- 23 fields

Compare By Name:
  1: ABSENCE_HIST -- 61 fields
  2: JOB -- 162 fields
  3: ZBD_JOBCODE_TBL -- 23 fields

Compare By Field Count:
  1: ZBD_JOBCODE_TBL -- 23 fields
  2: ABSENCE_HIST -- 61 fields
  3: JOB -- 162 fields

Please let me know if I missed anything or if you have any questions.


Share

4 Comments

  1. Idetrorce says:

    very interesting, but I don’t agree with you
    Idetrorce

  2. Hee4Haw says:

    Nice!

    Idetrorce,

    If you do not agee, can you post on how you would implement it ?
    If nothing, appreciate if we can start a healthy debate.

    Thanks for sharing your thoughts!

  3. venugopal says:

    Hi i have seen your comment on Arrays.
    i need your guidence on creating array and using it in Peoplecode App package.
    I have some logic written in SQR. Same thing i want create in App Package which can be used.
    Let me brief you my requirement.
    i have several parameters to be stored in an array which i will get from different validations and SQL tables for employees.which i will store it in a array. After finishing validations for all the employees i have pass those employee id and details some other system so i want to replicate in App package using Array can you guide me how i can design it in App package.

  4. digitaleagle says:

    Venugopal,

    Sorry, I almost missed this comment. It came while I was on vacation.

    Anyway, I created a separate post to try to answer your question. Let me know if you have additional questions.
    http://psst0101.wordpress.com/2010/07/31/arrays-question/

    Thanks,

    Stephen

2 Trackbacks

Leave a comment