Post Reply 
Sort Lists API: A collection of sort functions
09-08-2018, 09:06 PM (This post was last modified: 09-15-2018 10:56 PM by StephenG1CMZ.)
Post: #1
Sort Lists API: A collection of sort functions
A collection of Sort(List) functions (including some from the forum).
If you are looking for classic sorts (e.g. Bubble sort), look elsewhere (for now).

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
09-08-2018, 09:10 PM (This post was last modified: 09-27-2018 08:27 PM by StephenG1CMZ.)
Post: #2
RE: Sorts API: A collection of sort functions
Version 0.1 collects together the Sort functions previously contained in my List program (including Sortn from the forum), with minor implementation changes.
http://www.hpmuseum.org/forum/thread-9411.html
Requires List which should be compiled first.
Code:

Code

 LOCAL CRID:="Sorts API V0.1 © 2018 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of sort routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="Sorts.";//Name

 //IMPORT({List}); //Required

 LOCAL TYPELST:=TYPE({});
 LOCAL TYPEFLOAT:=TYPE(3.1);
 LOCAL TYPEINT:=TYPE(#3);
 LOCAL TYPESTR:=TYPE(" ");

 //Customise
 EXPORT SortableTypes:={TYPEFLOAT,TYPEINT,TYPESTR};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End

 //Forward
 IsSortablePortable(LST);
 SortL(LST);
 SortN(LST,NN);
 LOCAL NL:="\n";

 LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 EXPORT ListLastError:=0;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;

 EXPORT IsSortable(LST)
 //For now use Portable
 //Later: as SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 EXPORT IsSortedEQ(LST)
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortL(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT SortByKey(SORTS,KeyNum)
 //Sort lists by list number KeyNum (with some input guards)
 BEGIN
  IF 0<KeyNum≤SIZE(SORTS) THEN
   IF SIZE(SORTS)>1 AND SORTS(1)≠{} AND SORTS(2)≠{} THEN
    RETURN SortN(SORTS,KeyNum);
   END;
  ELSE
   //Potential:not all checked
   //List small, not containing lists, key out of range, key list unsortable
   RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
  END;
  RETURN SORTS;
 END;

 EXPORT SortByOccurrences(LST)
 //Returns {LSTV,LSTF} sorted by frequency of occurrence
 //reverse so most popular is 1st and index is approx rank 
 BEGIN
  TBD();
  //ListANS:=ListOCCURRENCES(LST);
  RETURN REVERSE(SortByKey(ListANS,2));
 END;

 EXPORT SortL(LST)
 //This implementation uses native SORT
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortL",EL,SortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 EXPORT SortsVERSION()
 BEGIN
  RETURN CRID;
 END;

 
 EXPORT Pyreverse(LST)
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //TBD: KeyFunc: Selects sort key from item
 BEGIN
  IF TYPE(KeyFunc)==TYPEFLOAT AND KeyFunc==0 THEN
   //0=None=NO FUNC
  ELSE
   TBD();
   RAISE(MN+"Pysort",EL,ValueError,"",1);//TBD
  END;
  RETURN IFTE(RReverse,SORT(Pyreverse(LST)),SORT(LST));
 END;

EXPORT ListPuzzles()
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso ()
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXPORT SortsExamples()
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);
  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  //PRINT(IsSortable(LL+{3.1}));

  PRINT(IsSorted(LL)); 
  //PRINT(ListIsTYPE({3.4},1-1));
  PRINT("Sort");
  //SortByABS
  //SortByKey
  //SortByOccurrences
  //TBD PRINT(SortByOccurrences({1,2,2,3,3,3}));
  //SortL
  PRINT(SortL(LL));
  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
 
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTS()
 BEGIN
  ABOUT();
  //SortExamples();
 END;

Version 0.2 is reworked to minimise the need for my "List" program.
I had hoped it would now only be needed for error handling, but in fact there is still a dependency on ListIsTYPE too..
New routines ReverseLOL, SortByCount, SortByABS.
Code:


 LOCAL CRID:="Sorts API V0.2 © 2018 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of sort routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="Sorts.";//Name
 //Also includes REVERSE functions

 //IMPORT({List}); //for error handling

 LOCAL TYPELST:=TYPE({});
 LOCAL TYPEFLOAT:=TYPE(3.1);
 LOCAL TYPEINT:=TYPE(#3);
 LOCAL TYPESTR:=TYPE(" ");

 //Customise
 EXPORT SortableTypes:={TYPEFLOAT,TYPEINT,TYPESTR};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End

 //Forward
 IsSortablePortable(LST);
 SortByKeyTBD(SORTS,Keynum);
 SortL(LST);
 SortN(LST,NN);
 LOCAL NL:="\n";

 LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 EXPORT ListLastError:=0;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;

 EXPORT IsSortable(LST)
 //For now use Portable
 //Later: as native SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 EXPORT IsSortedEQ(LST)
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortL(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT ReverseLOL(LSTS)
 //Reverse a list of lists
 //EG {{1,2},{3,4}} -> {{2,1},{4,3}}
 //NONRECURSIVE:TOP LISTS ONLY
 //ALL LISTS MUST BE REVERSIBLE
 BEGIN
  LOCAL II;
  ListANS:={};
  IF SIZE(LSTS) THEN
   //REVERSE EACH LST
   FOR II FROM 1 TO SIZE(LSTS) DO
    ListANS(II):=REVERSE(LSTS(II));
   END;//FOR  
  END;
  RETURN ListANS;
 END;

 EXPORT SortByABS(LST)
 BEGIN
  LOCAL TMP:={};
  IF SIZE(LST) THEN
   TMP:=SortN({ABS(LST),SIGN(LST)},1);
   RETURN TMP(1)*TMP(2);
  END;
  RETURN {};
 END;

 EXPORT SortByCount(LSTS,Keynum)
 //LSTS is {LSTV,LSTF} as returned by
 //ListOCCURRENCES(LST);
 //but additional fields are allowed
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 BEGIN
   IF SIZE(LSTS)≥Keynum THEN
    IF SIZE(LSTS(1))>1 AND SIZE(LSTS(Keynum))>1 THEN
     RETURN SortN(LSTS,K);
    END;
   END;
  RETURN {};
  //To reverse sequence call ReverseLOLS()
 END;
 //These routines are similar
 //Why does one fail TBD
 EXPORT SortByKeyTBD(LSTS,KeyNum)
 //Sort lists by list number KeyNum (with some input guards)
 //Hint: If this gives a data type error call SORTN directly (WHY?) 
 BEGIN
  IF 0<KeyNum≤SIZE(LSTS) AND SIZE(LSTS)>1 THEN
   IF LSTS(1)≠{} AND LSTS(2)≠{} THEN
    RETURN SortN(LSTS,KeyNum);
   END;
  ELSE
   //Potential:not all checked
   //List small, not containing lists, key out of range, key list unsortable
   RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
  END;
  RETURN {};
 END;

 EXPORT SortL(LST)
 //This implementation uses native SORT
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortL",EL,SortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 EXPORT SortsVERSION()
 BEGIN
  RETURN CRID;
 END;

 
 EXPORT Pyreverse(LST)
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //TBD: KeyFunc: Selects sort key from item
 BEGIN
  IF TYPE(KeyFunc)==TYPEFLOAT AND KeyFunc==0 THEN
   //0=None=NO FUNC
  ELSE
   TBD();
   RAISE(MN+"Pysort",EL,ValueError,"",1);//TBD
  END;
  RETURN IFTE(RReverse,SORT(Pyreverse(LST)),SORT(LST));
 END;

EXPORT ListPuzzles()
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso ()
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist (slower)",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXPORT SortsExamples()
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);

  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  PRINT(IsSortablePortable(LL));
  

  PRINT(IsSorted(LL)); 
  PRINT(IsSortedEQ(LL));
 
  PRINT("Reverse");

  PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
 
  PRINT("Sort");

  //SortByABS
  PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
 
  //SortByCount
  PRINT(SortByCount({{1,2,3},{10,30,20}},2)); // -> {{2,3,1},{10,20,30}} 
  //SortByKey

  //SortL
  PRINT(SortL(LL));

  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
  
  //SortByOccurrences
  PRINT(SortByCount({{1,2,3},{1,22,3}},2));
  PRINT(ReverseLOL(SortByCount({{1,2,3},{1,22,3}},2)));
 
  PRINT("Py");
  PRINT(Pyreverse({1,2,3}));
  PRINT(Pysort({1,22,3},0,0));
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTS()
 BEGIN
  ABOUT();
  //SortExamples();
 END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
09-15-2018, 10:52 PM (This post was last modified: 09-15-2018 10:55 PM by StephenG1CMZ.)
Post: #3
RE: Sort Lists API: A collection of sort functions
Version 0.3 now implements Pysort and fixes some bugs.

Code:


 LOCAL CRID:="SortL API V0.3 © 2018 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of Sort(List) routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="SortL.";//Name
 //Also includes REVERSE functions

 //IMPORT({List}); //Required

 LOCAL TYPELST:=TYPE({});
 LOCAL TYPEFLOAT:=TYPE(3.1);
 LOCAL TYPEINT:=TYPE(#3);
 LOCAL TYPESTR:=TYPE(" ");

 //Customise
 EXPORT SortableTypes:={TYPEFLOAT,TYPEINT,TYPESTR};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End

 //Forward
 IsSortablePortable(LST);
 SortByKey(SORTL,Keynum);
 SortByKeyTBD(SORTL,Keynum);
 SortLST(LST);
 SortN(LST,NN);
 LOCAL NL:="\n";

 LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 EXPORT ListLastError:=0;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;

EXPORT RAISE(MN,ERRLST,ERR,CULPRIT,SEVERITY)
 BEGIN
 END;
 
 EXPORT IsSortable(LST)
 //For now use Portable
 //Later: as native SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 EXPORT IsSortedEQ(LST)
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortLST(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT ReverseLOL(LSTS)
 //Reverse a list of lists
 //EG {{1,2},{3,4}} -> {{2,1},{4,3}}
 //NONRECURSIVE:2ND LEVEL LISTS ONLY
 //ALL LISTS MUST BE REVERSIBLE
 BEGIN
  LOCAL II;
  ListANS:={};
  IF SIZE(LSTS) THEN
   //REVERSE EACH LST
   FOR II FROM 1 TO SIZE(LSTS) DO
    ListANS(II):=REVERSE(LSTS(II));
   END;//FOR  
  END;
  RETURN ListANS;
 END;

 EXPORT SortByABS(LST)
 BEGIN
  LOCAL TMP:={};
  IF SIZE(LST) THEN
   TMP:=SortN({ABS(LST),SIGN(LST)},1);
   RETURN TMP(1)*TMP(2);
  END;
  RETURN {};
 END;

 //The following could return just the valuesO
 //or Values and counts in 2 lists
 //Whichis preferred?

 EXPORT SortByCounts(LST)
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 
 BEGIN
  ListANS:=ListCOUNTS(LST);//To omit this step, use SortByKey directly
  RETURN SortByKey(ListANS,2);
 END;

 EXPORT SortByKey(LSTS,Keynum)
 //LSTS is {LSTV,LSTF} as returned by
 //ListCOUNTS(LST);
 //but additional fields are allowed
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 
 BEGIN
   IF SIZE(LSTS)≥Keynum THEN
    IF SIZE(LSTS(1))>1 AND SIZE(LSTS(Keynum))>1 THEN
     RETURN SortN(LSTS,K);
    END;
   END;
  RETURN {};
  //To reverse sequence call ReverseLOLS()
 END;
 //These routines are similar
 //Why does one fail TBD
 EXPORT SortByKeyTBD(LSTS,KeyNum)
 //Sort lists by list number KeyNum (with some input guards)
 //Hint: If this gives a data type error call SORTN directly (WHY?) 
 BEGIN
  IF 0<KeyNum≤SIZE(LSTS) AND SIZE(LSTS)>1 THEN
   IF LSTS(1)≠{} AND LSTS(2)≠{} THEN
    RETURN SortN(LSTS,KeyNum);
   END;
  ELSE
   //Potential:not all checked
   //List small, not containing lists, key out of range, key list unsortable
   RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
  END;
  RETURN {};
 END;

 EXPORT SortLST(LST)
 //This implementation uses native SORT
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortL",EL,SortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 EXPORT SortsVERSION()
 BEGIN
  RETURN CRID;
 END;

 
 EXPORT Pyreverse(LST)
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //PyOpt KeyFunc: STRING EG "ABS" (NULL=NONE)
 //PyOpt PRReverse BOOL
 BEGIN
  LOCAL TMP;
  IF KeyFunc=="" THEN
   ListANS:=SORT(LST);
   RETURN IFTE(RReverse,Pyreverse(ListANS),ListANS);
  END;
  TMP:=EXPR(KeyFunc+"(LST)");
  ListANS:=SortN({LST,TMP},2);
  RETURN IFTE(RReverse,Pyreverse(ListANS(1)),ListANS(1)); 
 END;

EXPORT ListPuzzles()
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso ()
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist (slower)",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXPORT SortsExamples()
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);

  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  PRINT(IsSortablePortable(LL));
  

  PRINT(IsSorted(LL)); 
  PRINT(IsSortedEQ(LL));
 
  PRINT("Reverse");

  PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
 
  PRINT("Sort");

  //SortByABS
  PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
 
  //SortByCounts
  PRINT(SortByCounts({1,2,3,2,3,3})); // -> {{1,2,3},{1,2,3}} 
  //SortByKey
  PRINT(SortByKey({{1,2,3},{10,30,20}},2)); //-> {{1,3,2},{10,20,30}}
  PRINT(SortByKey({{1,2,3},{1,22,3}},2));
  PRINT(ReverseLOL(SortByKey({{1,2,3},{1,22,3}},2)));

  //SortL
  PRINT(SortLST(LL));

  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
  
  PRINT("Py");
  PRINT(Pyreverse({1,2,3}));
  PRINT(Pysort({1,22,3},"",0));
  PRINT(Pysort({1,22,3},"ABS",0));
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTL()
 BEGIN
  ABOUT();
  //SortExamples();
 END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
09-27-2018, 09:19 PM (This post was last modified: 09-27-2018 09:25 PM by StephenG1CMZ.)
Post: #4
RE: Sort Lists API: A collection of sort functions
Version 0.4C implements IsSortableNative to track the functionality of the native SORT.
Some functions are unexported to minimise global effects.
(0.4C Corrects minor errors in 0.4,0.4A and 0.4B)
Code:

LOCAL CRID:="SortL API V0.4C © 2018 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of Sort(List) routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="SortL.";//Name
 //Also includes REVERSE functions
 //NB REVERSE REVERSES A LIST (WHICH MIGHT HAVE BEEN SORTED)
 //(IT DOES NOT OF ITSELF REVERSE-SORT DESPITE BEING IN THIS SORTL PROGRAM)


 //IMPORT({List}); //Required
 //Some exportables (ex) omitted to minimise global impact
 //Customise
 EXPORT SortableNumericTypes:={TYPEFLOAT,TYPEINT};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End

 //Forward
 IsSortablePortable(LST);
 SortByKey(SORTL,Keynum);
 SortByKeyTBD(SORTL,Keynum);
 SortLST(LST);
 SortN(LST,NN);
 LOCAL NL:="\n";

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;
 
 IsSortable(LST) //ex
 //For now use Portable
 //Later: as native SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortableNative(LST)
 //Checks whether the contents of LST are natively sortable
 //Returns 1 TYPESTR only
 //Returns 1 SortableNumeric
 //NB Lists and keys can be sorted but lists alone no
 BEGIN
  LOCAL TP;
  IF SIZE(LST) THEN
   TP:=TYPE(LST(1));
   CASE
    IF TP==TYPESTR THEN 
     RETURN ListIsTYPE(LST,TYPESTR);
    END;
    IF POS(SortableNumericTypes,TP) THEN 
     RETURN ListIsTYPE(LST,SortableNumericTypes);
    END;
    DEFAULT
     RETURN 0;//UNSORTABLE
   END;//CASE
  END;
  RETURN 1;//EMPTY INDETERMINATE
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  LOCAL SortableTypes:=CONCAT(SortableNumericTypes,TYPESTR);
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 IsSortedEQ(LST) //EX
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortLST(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT ReverseLOL(LSTS)
 //Reverse a list of lists
 //EG {{1,2},{3,4}} -> {{2,1},{4,3}}
 //NONRECURSIVE:2ND LEVEL LISTS ONLY
 //ALL LISTS MUST BE REVERSIBLE
 BEGIN
  LOCAL II;
  ListANS:={};
  IF SIZE(LSTS) THEN
   //REVERSE EACH LST
   FOR II FROM 1 TO SIZE(LSTS) DO
    ListANS(II):=REVERSE(LSTS(II));
   END;//FOR  
  END;
  RETURN ListANS;
 END;

 EXPORT SortByABS(LST)
 //Return SORTEDL
 //Note that integers return floats
 BEGIN
  LOCAL TMP:={};
  
  IF SIZE(LST) THEN
   TMP:=SortN({ABS(LST),SIGN(LST)},1);
   RETURN TMP(1)*TMP(2);
  END;
  RETURN {};
 END;

 EXPORT SortByCounts(LST)
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //Return {SORTEDL,SORTEDCOUNTS}
 BEGIN
  ListANS:=ListCOUNTS(LST);//To omit this step, use SortByKey directly
  RETURN SortByKey(ListANS,2);
 END;

 EXPORT SortByKeyLST(LST,KEYLST)
 //Sort LST using KEYLST
 //LST must be sortable. LOL will fail.
 //Return {SORTEDL,SORTEDKEYLST}
 BEGIN
  IF SIZE(LST) AND SIZE(KEYLST) THEN
   RETURN SortN({LST,KEYLST},2);
  END;
  RETURN {};
 END;

 EXPORT SortByKeyNUM(LSTS,Keynum)
 //LSTS is {LSTV,LSTF} as returned by
 //ListCOUNTS(LST);
 //but additional fields are allowed
 //Returns {SORTED,LSTF} sorted by sort key criteria
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //BUG:ONLY SORTS TWO LISTS,
 //BUT CALLING SortN direcLy works
 BEGIN
   IF SIZE(LSTS)≥Keynum THEN
    IF SIZE(LSTS(1))>1 AND SIZE(LSTS(Keynum))>1 THEN
     RETURN SortN(LSTS,Keynum);
    END;
   END;
  RETURN {};
  //To reverse sequence call ReverseLOLS()
 END;
 //These routines are similar
 //Why does one fail TBD
 EXPORT SortByKeyTBD(LSTS,KeyNum)
 //Sort lists by list number KeyNum (with some input guards)
 //Hint: If this gives a data type error call SORTN directly (WHY?) 
 BEGIN
  IF 0<KeyNum≤SIZE(LSTS) AND SIZE(LSTS)>1 THEN
   IF LSTS(1)≠{} AND LSTS(2)≠{} THEN
    RETURN SortN(LSTS,KeyNum);
   END;
  ELSE
   //Potential:not all checked
   //List small, not containing lists, key out of range, key list unsortable
   RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
  END;
  RETURN {};
 END;

 EXPORT SortLST(LST) //ex
 //This implementation uses native SORT
 //It is convenient to export when comparing with other sorts
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortL",EL,SortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 SortsVERSION() //ex
 BEGIN
  RETURN CRID;
 END;

 
 Pyreverse(LST) //ex
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

 EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //PyOpt KeyFunc: STRING EG "ABS" (NULL=NONE)
 //PyOpt PRReverse BOOL
 BEGIN
  LOCAL TMP;
  IF KeyFunc=="" THEN
   ListANS:=SORT(LST);
   RETURN IFTE(RReverse,Pyreverse(ListANS),ListANS);
  END;
  TMP:=EXPR(KeyFunc+"(LST)");
  ListANS:=SortN({LST,TMP},2);
  RETURN IFTE(RReverse,Pyreverse(ListANS(1)),ListANS(1)); 
 END;

 ListPuzzles() //EX
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso () //ex
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist (slower)",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXPORT SortsExamples() //ex
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);

  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  PRINT(IsSortablePortable(LL));
  

  PRINT(IsSorted(LL)); 
  PRINT(IsSortedEQ(LL));
 
  PRINT("Reverse");

  PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
 
  PRINT("Sort");

  //SortByABS
  PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
 
  //SortByCounts
  PRINT(SortByCounts({1,2,3,2,3,3})); // -> {{1,2,3},{1,2,3}} 
  //SortByKey
  PRINT(SortByKeyNUM({{1,2,3},{10,30,20}},2)); //-> {{1,3,2},{10,20,30}}
  PRINT(SortByKeyNUM({{1,2,3},{1,22,3}},2));
  PRINT(ReverseLOL(SortByKeyNUM({{1,2,3},{1,22,3}},2)));

  //SortL
  PRINT(SortLST(LL));

  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
  
  PRINT("Py");
  PRINT(Pyreverse({1,2,3}));
  PRINT(Pysort({1,22,3},"",0));
  PRINT(Pysort({1,22,3},"ABS",0));
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTL()
 BEGIN
  LOCAL LST:={};
  ABOUT();
  //SortExamples();
   
 END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
12-03-2019, 11:42 PM (This post was last modified: 12-03-2019 11:47 PM by StephenG1CMZ.)
Post: #5
RE: Sort Lists API: A collection of sort functions
Version 0.5 implements SortByFun in response to

https://www.hpmuseum.org/forum/thread-6179.html
Code:
 
LOCAL CRID:="SortL API V0.5 © 2019 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of Sort(List) routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="SortL.";//Name
 //Also includes REVERSE functions
 //NB REVERSE REVERSES A LIST (WHICH MIGHT HAVE BEEN SORTED)
 //(IT DOES NOT OF ITSELF REVERSE-SORT DESPITE BEING IN THIS SORTL PROGRAM)

 //IMPORT({PPLX}); 
 //IMPORT({List}); //Required
 //Some exportables (ex) omitted to minimise global impact
 //Customise
 EXPORT SortableNumericTypes:={TYPEREAL,TYPEINT};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End

 //Forward
 IsSortablePortable(LST);
 SortByKey(SORTL,Keynum);
 SortByKeyTBD(SORTL,Keynum);
 SortLST(LST);
 SortN(LST,NN);
 LOCAL NL:="\n";

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;
 
 IsSortable(LST) //ex
 //For now use Portable
 //Later: as native SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortableNative(LST)
 //Checks whether the contents of LST are natively sortable
 //Returns 1 TYPESTR only
 //Returns 1 SortableNumeric
 //NB Lists and keys can be sorted but lists alone no
 BEGIN
  LOCAL TP;
  IF SIZE(LST) THEN
   TP:=TYPE(LST(1));
   CASE
    IF TP==TYPESTR THEN 
     RETURN ListIsTYPE(LST,TYPESTR);
    END;
    IF POS(SortableNumericTypes,TP) THEN 
     RETURN ListIsTYPE(LST,SortableNumericTypes);
    END;
    DEFAULT
     RETURN 0;//UNSORTABLE
   END;//CASE
  END;
  RETURN UNK1;//EMPTY INDETERMINATE
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  LOCAL SortableTypes:=CONCAT(SortableNumericTypes,TYPESTR);
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 IsSortedEQ(LST) //EX
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortLST(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT ReverseLOL(LSTS)
 //Reverse a list of lists
 //EG {{1,2},{3,4}} -> {{2,1},{4,3}}
 //NONRECURSIVE:2ND LEVEL LISTS ONLY
 //ALL LISTS MUST BE REVERSIBLE
 BEGIN
  LOCAL II;
  ListANS:={};
  IF SIZE(LSTS) THEN
   //REVERSE EACH LST
   FOR II FROM 1 TO SIZE(LSTS) DO
    ListANS(II):=REVERSE(LSTS(II));
   END;//FOR  
  END;
  RETURN ListANS;
 END;

 EXPORT SortByABS(LST)
 //Return LST SORTED BY ABS VALUE
 //Note that #integers return floats
 //ALT: USE SortByFun(LST,ABS(LST))
 //SortByABS is quicker
 BEGIN
  LOCAL TMP:={};
  
  IF SIZE(LST) THEN
   TMP:=SortN({ABS(LST),SIGN(LST)},1);
   RETURN TMP(1)*TMP(2);
  END;
  RETURN {};
 END;

 EXPORT SortByCounts(LST)
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //Return {SORTEDL,SORTEDCOUNTS}
 BEGIN
  ListANS:=ListCOUNTS(LST);//To omit this step, use SortByKey directly
  RETURN SortByKey(ListANS,2);
 END;

 EXPORT SortByFun(LST,SortFun)
 //Sort using SortFun as your sort function 
 //EG SortByFun(LST,ABS(LST)) //BUT SortByABS is faster (Again #integers return floats)
 //EG SortByFun(LST,MYSORTFUN(LST[,ITEM]))
 //Note: The function name alone is not sufficient
 //See https://www.hpmuseum.org/forum/thread-6179.html for alternative CAS syntaxes
 //ALT: Use Pysort("fun")
 BEGIN
  LOCAL SORTORDER;
  LOCAL SORTED:={{},{}};//GUARD EMPTY LIST
  
  IF SIZE(LST) THEN
   SORTORDER:=SortFun;
   SORTED:=Sortn({LST,SORTORDER},2);
  END;
  RETURN SORTED(1); //TO SEE THE SORT ORDER INSTEAD:2
 END;

 EXPORT SortByKeyLST(LST,KEYLST)
 //Sort LST using KEYLST
 //LST must be sortable. LOL will fail.
 //Return {SORTEDL,SORTEDKEYLST}
 BEGIN
  IF SIZE(LST) AND SIZE(KEYLST) THEN
   RETURN SortN({LST,KEYLST},2);
  END;
  RETURN {};
 END;

 EXPORT SortByKeyNUM(LSTS,Keynum)
 //LSTS is {LSTV,LSTF} as returned by
 //ListCOUNTS(LST);
 //but additional fields are allowed
 //Returns {SORTED,LSTF} sorted by sort key criteria
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //BUG:ONLY SORTS TWO LISTS,
 //BUT CALLING SortN direcLy works
 BEGIN
   IF SIZE(LSTS)≥Keynum THEN
    IF SIZE(LSTS(1))>1 AND SIZE(LSTS(Keynum))>1 THEN
     RETURN SortN(LSTS,Keynum);
    END;
   END;
  RETURN {};
  //To reverse sequence call ReverseLOLS()
 END;
 //These routines are similar
 //Why does one fail TBD
 EXPORT SortByKeyTBD(LSTS,KeyNum)
 //Sort lists by list number KeyNum (with some input guards)
 //Hint: If this gives a data type error call SORTN directly (WHY?) 
 BEGIN
  IF 0<KeyNum≤SIZE(LSTS) AND SIZE(LSTS)>1 THEN
   IF LSTS(1)≠{} AND LSTS(2)≠{} THEN
    RETURN SortN(LSTS,KeyNum);
   END;
  ELSE
   //Potential:not all checked
   //List small, not containing lists, key out of range, key list unsortable
   RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
  END;
  RETURN {};
 END;

 EXPORT SortLST(LST) //ex
 //This implementation uses native SORT
 //It is convenient to export when comparing with other sorts
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortL",EL,SortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 SortsVERSION() //ex
 BEGIN
  RETURN CRID;
 END;

 
 Pyreverse(LST) //ex
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

 EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //PyOpt KeyFunc: STRING EG "ABS" (NULL=NONE)
 //PyOpt PRReverse BOOL
 //ALT: Use SortByFun(LST,Fun(LST...))
 //Note: The Py syntax is optional fun without strings
 //Using strings here allows optional null string to be handled
 //The alt SortByFun avoids strings but requires a function
 
 BEGIN
  LOCAL TMP;
  IF KeyFunc=="" THEN
   ListANS:=SORT(LST);
   RETURN IFTE(RReverse,Pyreverse(ListANS),ListANS);
  END;
  TMP:=EXPR(KeyFunc+"(LST)");
  ListANS:=SortN({LST,TMP},2);
  RETURN IFTE(RReverse,Pyreverse(ListANS(1)),ListANS(1)); 
 END;

 ListPuzzles() //EX
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso () //ex
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist (slower)",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXPORT SortsExamples() //ex
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);

  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  PRINT(IsSortablePortable(LL));
  

  PRINT(IsSorted(LL)); 
  PRINT(IsSortedEQ(LL));
 
  PRINT("Reverse");

  PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
 
  PRINT("Sort");

  //SortByABS
  PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
 
  //SortByCounts
  PRINT(SortByCounts({1,2,3,2,3,3})); // -> {{1,2,3},{1,2,3}} 
  //SortByKey
  PRINT(SortByKeyNUM({{1,2,3},{10,30,20}},2)); //-> {{1,3,2},{10,20,30}}
  PRINT(SortByKeyNUM({{1,2,3},{1,22,3}},2));
  PRINT(ReverseLOL(SortByKeyNUM({{1,2,3},{1,22,3}},2)));

  //SortL
  PRINT(SortLST(LL));

  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
  
  PRINT("Py");
  PRINT(Pyreverse({1,2,3}));
  PRINT(Pysort({1,22,3},"",0));
  PRINT(Pysort({1,22,3},"ABS",0));
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTL()
 BEGIN
  LOCAL LST:={};
  ABOUT();
  //SortExamples();
   
 END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
12-06-2019, 12:21 AM (This post was last modified: 12-06-2019 12:25 AM by StephenG1CMZ.)
Post: #6
RE: Sort Lists API: A collection of sort functions
Version 0.6 implements
SortFromItem: Sort by sort distance from an item
and
SortFromItems: Sort by minimum sort distance from a list of items.
The sort distance is a simple ABS(LST-MIN(Items)).


Code:


 LOCAL CRID:="SortL API V0.6 © 2019 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of Sort(List) routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="SortL.";//Name
 
 //Dictionary
 //ITEM: an element of a list (or a value which could be in a list)
 //ITEMS: a list of 0..n ITEMs
 //LOL or LSTS: List Of lists EG {{1,2},{3,4}}
 //REVERSE: reverses a list (i.e. to reverse-Sort do REVERSE(SORT()) )
 //All lists may be empty (except: SortN)

 //IMPORT({PPLX}); //TYPE
 //IMPORT({List}); //Required
 //Some exportables (ex) omitted to minimise global impact
 //Customise
 EXPORT SortableNumericTypes:={TYPEREAL,TYPEINT};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End Custom

 //Forward
 IsSortablePortable(LST);
 SortByKey(SORTL,Keynum);
 SortByKeyTBD(SORTL,Keynum);
 SortLST(LST);
 SortN(LST,NN);

 LOCAL NL:="\n";

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;
 
 IsSortable(LST) //ex
 //For now use Portable
 //Later: as native SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortableNative(LST)
 //Checks whether the contents of LST are natively sortable
 //Returns 1 TYPESTR only
 //Returns 1 SortableNumeric
 //NB Lists and keys can be sorted but lists alone no
 BEGIN
  LOCAL TP;
  IF SIZE(LST) THEN
   TP:=TYPE(LST(1));
   CASE
    IF TP==TYPESTR THEN 
     RETURN ListIsTYPE(LST,TYPESTR);
    END;
    IF POS(SortableNumericTypes,TP) THEN 
     RETURN ListIsTYPE(LST,SortableNumericTypes);
    END;
    DEFAULT
     RETURN 0;//UNSORTABLE
   END;//CASE
  END;
  RETURN UNK1;//EMPTY INDETERMINATE
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  LOCAL SortableTypes:=CONCAT(SortableNumericTypes,TYPESTR);
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 IsSortedEQ(LST) //EX
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortLST(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT ReverseLOL(LSTS)
 //Reverse a list of lists
 //EG {{1,2},{3,4}} -> {{2,1},{4,3}}
 //NONRECURSIVE:2ND LEVEL LISTS ONLY
 //ALL LISTS MUST BE REVERSIBLE
 BEGIN
  LOCAL II;
  ListANS:={};
  IF SIZE(LSTS) THEN
   //REVERSE EACH LST
   FOR II FROM 1 TO SIZE(LSTS) DO
    ListANS(II):=REVERSE(LSTS(II));
   END;//FOR  
  END;
  RETURN ListANS;
 END;

 EXPORT SortByABS(LST)
 //Return LST SORTED BY ABS VALUE
 //Note that #integers return floats
 //ALT: USE SortByFun(LST,ABS(LST))
 //SortByABS is quicker
 BEGIN
  LOCAL TMP:={};
  
  IF SIZE(LST) THEN
   TMP:=SortN({ABS(LST),SIGN(LST)},1);
   RETURN TMP(1)*TMP(2);
  END;
  RETURN {};
 END;

 EXPORT SortByCounts(LST)
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //Return {SORTEDL,SORTEDCOUNTS}
 BEGIN
  ListANS:=ListCOUNTS(LST);//To omit this step, use SortByKey directly
  RETURN SortByKey(ListANS,2);
 END;

 EXPORT SortByFun(LST,SortFun)
 //Sort using SortFun as your sort function 
 //EG SortByFun(LST,ABS(LST)) //BUT SortByABS is faster (Again #integers return floats)
 //EG SortByFun(LST,MYSORTFUN(LST[,ITEM]))
 //Note: The function name alone is not sufficient
 //See https://www.hpmuseum.org/forum/thread-6179.html for alternative CAS syntaxes
 //ALT: Use Pysort("fun")
 BEGIN
  LOCAL SORTORDER;
  LOCAL SORTED:={{},{}};//GUARD EMPTY LIST
  
  IF SIZE(LST) THEN
   SORTORDER:=SortFun;
   SORTED:=Sortn({LST,SORTORDER},2); 
  END;
  RETURN SORTED(1); //TO SEE THE SORT ORDER INSTEAD:2
 END;

 EXPORT SortByKeyLST(LST,KEYLST)
 //Sort LST using KEYLST
 //LST must be sortable. LOL will fail.
 //Return {SORTEDL,SORTEDKEYLST}
 BEGIN
  IF SIZE(LST) AND SIZE(KEYLST) THEN
   RETURN SortN({LST,KEYLST},2);
  END;
  RETURN {};
 END;

 EXPORT SortByKeyNUM(LSTS,Keynum)
 //LSTS is {LSTV,LSTF} as returned by
 //ListCOUNTS(LST);
 //but additional fields are allowed
 //Returns {SORTED,LSTF} sorted by sort key criteria
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //BUG:ONLY SORTS TWO LISTS,
 //BUT CALLING SortN direcLy works
 BEGIN
   IF SIZE(LSTS)≥Keynum THEN
    IF SIZE(LSTS(1))>1 AND SIZE(LSTS(Keynum))>1 THEN
     RETURN SortN(LSTS,Keynum);
    END;
   END;
  RETURN {};
  //To reverse sequence call ReverseLOLS()
 END;
 //These routines are similar
 //Why does one fail TBD
 EXPORT SortByKeyTBD(LSTS,KeyNum)
 //Sort lists by list number KeyNum (with some input guards)
 //Hint: If this gives a data type error call SORTN directly (WHY?) 
 BEGIN
  IF 0<KeyNum≤SIZE(LSTS) AND SIZE(LSTS)>1 THEN
   IF LSTS(1)≠{} AND LSTS(2)≠{} THEN
    RETURN SortN(LSTS,KeyNum);
   END;
  ELSE
   //Potential:not all checked
   //List small, not containing lists, key out of range, key list unsortable
   RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
  END;
  RETURN {};
 END;

 EXPORT SortFromItem(LST,ITEM)
  //Return simple sort distance
  //Return LST SORTED BY NUMERICAL ABS VALUE FROM ITEM
  //Note that #integers return floats
  //=SortFromItems(LST,{ITEM})
  //ALT: USE SortByFun(LST,MYSORTFUN(LST...))
 BEGIN
  LOCAL TMP:={}; 
  IF SIZE(LST) THEN  
   TMP:=SortByFun(LST,ABS(LST-ITEM));  
  END;
  RETURN TMP;
 END;

 EXPORT SortFromItems(LST,ITEMS)
 //Sort by min sort distance from a list of items
 //#integers return floats
 //EMPTY LISTS: RETURN EMPTY LIST
 // (or: perhaps empty ITEMS should simply SORT(LST)?) 
 BEGIN
  LOCAL DX:={};
  LOCAL TMP:={{},{}}; 
  LOCAL II;
  IF SIZE(LST) AND SIZE(ITEMS) THEN 
   //IF SIZE(ITEMS)==1 THEN //OPTIONAL OPTIMISE
   // RETURN SortFromItem(LST,ITEMS(1));
   //END;
   //DX:=sort distance from nearest ITEM
   DX:=MAKELIST(MIN(ABS(LST(II)-ITEMS)),II,1,SIZE(LST));
   TMP:=SortN({LST,DX},2);  
  END;
  //PRINT(TMP);
  RETURN TMP(1);
 END;

 EXPORT SortLST(LST) //ex
 //This implementation uses native SORT
 //It is convenient to export when comparing with other sorts
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortL",EL,SortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 SortsVERSION() //ex
 BEGIN
  RETURN CRID;
 END;

 
 Pyreverse(LST) //ex
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

 EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //PyOpt KeyFunc: STRING EG "ABS" (NULL=NONE)
 //PyOpt PRReverse BOOL
 //ALT: Use SortByFun(LST,Fun(LST...))
 //Note: The Py syntax is optional fun without strings
 //Using strings here allows optional null string to be handled
 //The alt SortByFun avoids strings but requires a function
 
 BEGIN
  LOCAL TMP;
  IF KeyFunc=="" THEN
   ListANS:=SORT(LST);
   RETURN IFTE(RReverse,Pyreverse(ListANS),ListANS);
  END;
  TMP:=EXPR(KeyFunc+"(LST)");
  ListANS:=SortN({LST,TMP},2);
  RETURN IFTE(RReverse,Pyreverse(ListANS(1)),ListANS(1)); 
 END;

 ListPuzzles() //EX
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso () //ex
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist (slower)",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXAMPLESORTFROM()
 //EG DISTANCE FROM FIRST AID POSTS AT 5 mile intervals along a half marathon
 BEGIN
  LOCAL ITEMS:={0,5,10};//FIRST AID POSTS
  //LOCAL LST:={10,5,−20,−5,20,−10};
  LOCAL LST:={1,2,3,4,5,6,7,8,9,10,11,12,13};
  LOCAL OUTLST;
  PRINT();
  PRINT(OUTLST:=SortFromItems(LST,ITEMS));//CLOSEST LISTED FIRST
 END;

 EXPORT SortsExamples() //ex
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);

  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  PRINT(IsSortablePortable(LL));
  

  PRINT(IsSorted(LL)); 
  PRINT(IsSortedEQ(LL));
 
  PRINT("Reverse");

  PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
 
  PRINT("Sort");

  //SortByABS
  PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
 
  //SortByCounts
  PRINT(SortByCounts({1,2,3,2,3,3})); // -> {{1,2,3},{1,2,3}} 
  //SortByKey
  PRINT(SortByKeyNUM({{1,2,3},{10,30,20}},2)); //-> {{1,3,2},{10,20,30}}
  PRINT(SortByKeyNUM({{1,2,3},{1,22,3}},2));
  PRINT(ReverseLOL(SortByKeyNUM({{1,2,3},{1,22,3}},2)));

  //SortL
  PRINT(SortLST(LL));

  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
  
  PRINT("Py");
  PRINT(Pyreverse({1,2,3}));
  PRINT(Pysort({1,22,3},"",0));
  PRINT(Pysort({1,22,3},"ABS",0));
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTL()
 BEGIN
  LOCAL LST:={};
  ABOUT();
  //SortExamples();
   
 END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
12-11-2019, 07:24 PM (This post was last modified: 12-11-2019 07:26 PM by StephenG1CMZ.)
Post: #7
RE: Sort Lists API: A collection of sort functions
Version 0.7

SortByKey functions rewritten
SortByIndex implemented

Code:



 LOCAL CRID:="SortL API V0.7 © 2019 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of Sort(List) routines brought to you by StephenG1CMZ,\n with some from the forum.";
 LOCAL MN:="SortL.";//Name
 
 //Dictionary
 //ITEM: an element of a list (or a value which could be in a list)
 //ITEMS: a list of 0..n ITEMs
 //KEYLST: sorting this sorts your other list(s)
 //LST: a list 
 //LOL or LSTS: List Of lists EG {{1,2},{3,4}} (just {{1,2}} may be OK)
 //REVERSE: reverses a list (i.e. to reverse-Sort do REVERSE(SORT()) )
 //All lists may be empty (except: SortN)

 //IMPORT({PPLX}); //TYPE
 //IMPORT({List}); //Required
 //Some exportables (ex) omitted to minimise global impact
 //Customise
 EXPORT SortableNumericTypes:={TYPEREAL,TYPEINT};
 LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
 LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
 //LOCAL SL:=1;
 //NB To test: sort >1 item
 //End Custom

 //Forward
 IsSortablePortable(LST);
 SortByKey(SORTL,Keynum);
 SortLST(LST);
 SortN(LST,NN);

 LOCAL NL:="\n";

 //ERR 
 LOCAL ListErrK:=1;
 LOCAL PyErrK:=3;
 LOCAL ERRKIND:={"","Error","","Py Error"};

 EXPORT EL:={
  "(/0) DivideBy0",
  "IndexOutofBoundsException",
  "ListIsEmptyError",
  "ListIsFullError",
  "ListSortError",
  "ListStatisticsError",
  "ItemNotFoundError",
  "ValueError"
 };
 //ERRNO IS ARBITRARY:INDEXES ERRLST
 EXPORT DivBy0Error:=1;
 LOCAL IndexOutOfBoundsException:=2;//List J
 EXPORT ListIsEmptyError:=3;
 LOCAL ListIsFullError:=4;//UNUSED YET
 LOCAL SortError:=5;
 EXPORT ListStatisticsError:=6;
 EXPORT ItemNotFoundError:=7;//List Py
 EXPORT ValueError:=8; // Py
 
 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT);
 END;

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;
 
 IsSortable(LST) //ex
 //For now use Portable
 //Later: as native SORT
 BEGIN
  RETURN IsSortablePortable(LST);
 END;

 EXPORT IsSortableNative(LST)
 //Checks whether the contents of LST are natively sortable
 //Returns 1 TYPESTR only
 //Returns 1 SortableNumeric
 //NB Lists and keys can be sorted but lists alone no
 BEGIN
  LOCAL TP;
  IF SIZE(LST) THEN
   TP:=TYPE(LST(1));
   CASE
    IF TP==TYPESTR THEN 
     RETURN ListIsTYPE(LST,TYPESTR);
    END;
    IF POS(SortableNumericTypes,TP) THEN 
     RETURN ListIsTYPE(LST,SortableNumericTypes);
    END;
    DEFAULT
     RETURN 0;//UNSORTABLE
   END;//CASE
  END;
  RETURN UNK1;//EMPTY INDETERMINATE
 END;

 EXPORT IsSortablePortable(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is SORTL implemented on that type yet
 //NOTE:
 //IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
 //do not assume SORT({mixed}) will deliver your expectations
 //NB The current algorithm reports {1,"4"} as sortable
 //But native sort wont
 //The Portable variant assumes strings and numerics are sortable.
 BEGIN
  LOCAL SortableTypes:=CONCAT(SortableNumericTypes,TYPESTR);
  IF TYPE(LST)==TYPELST THEN
   IF SIZE(LST) THEN
    RETURN ListIsTYPE(LST,SortableTypes);
   END;
   RETURN UNK0;//EMPTY
  END;
  RETURN 0;//NOT LIST:CANNOT BE SORTED
 END;

 IsSortedEQ(LST) //EX
 //Tells whether a list is sorted...inefficiently
 //By sorting it and checking equality
 //(Useful for testing)
 BEGIN
  ListANS:=SortLST(LST);
  RETURN EQ(ListANS,LST);
 END;
 
 EXPORT IsSorted(LST)
 //Looping until 1st descending will/may be quicker TBD
 BEGIN
  RETURN IsSortedEQ(LST);
 END;

 EXPORT ReverseLOL(LSTS)
 //Reverse a list of lists
 //EG {{1,2},{3,4}} -> {{2,1},{4,3}}
 //NONRECURSIVE:2ND LEVEL LISTS ONLY
 //ALL LISTS MUST BE REVERSIBLE
 BEGIN
  LOCAL II;
  ListANS:={};
  IF SIZE(LSTS) THEN
   //REVERSE EACH LST
   FOR II FROM 1 TO SIZE(LSTS) DO
    ListANS(II):=REVERSE(LSTS(II));
   END;//FOR  
  END;
  RETURN ListANS;
 END;

 EXPORT SortByABS(LST)
 //Return LST SORTED BY ABS VALUE
 //Note that #integers return floats
 //ALT: USE SortByFun(LST,ABS(LST))
 //SortByABS is quicker
 BEGIN
  LOCAL TMP:={};
  
  IF SIZE(LST) THEN
   TMP:=SortN({ABS(LST),SIGN(LST)},1);
   RETURN TMP(1)*TMP(2);
  END;
  RETURN {};
 END;

 EXPORT SortByCounts(LST)
 //Returns {LSTV,LSTF} sorted by frequency of occurrence 
 //EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
 //Return {SORTEDL,SORTEDCOUNTS}
 BEGIN
  ListANS:=ListCOUNTS(LST);//To omit this step, use SortByKey directly
  RETURN SortByKey(ListANS,2);
 END;

 EXPORT SortByFun(LST,SortFun)
 //Sort using SortFun as your sort function 
 //EG SortByFun(LST,ABS(LST)) //BUT SortByABS is faster (Again #integers return floats)
 //EG SortByFun(LST,MYSORTFUN(LST[,ITEM]))
 //Note: The function name alone is not sufficient
 //See https://www.hpmuseum.org/forum/thread-6179.html for alternative CAS syntaxes
 //ALT: Use Pysort("fun")
 BEGIN
  LOCAL SORTORDER;
  LOCAL SORTED:={{},{}};//GUARD EMPTY LIST
  
  IF SIZE(LST) THEN
   SORTORDER:=SortFun;
   SORTED:=SortN({LST,SORTORDER},2); 
  END;
  RETURN SORTED(1); //TO SEE THE SORT ORDER INSTEAD:2
 END;

 EXPORT SortByIndex(LST,XLST)
 //Return the indexes from LST specified by XLST
 //A partial list is valid, as are repetitions
 //An entry in XLST > SIZE(LST) could be checked 1st
 BEGIN
  LOCAL II;
  LOCAL TMP:={0};
  IF SIZE(LST) AND SIZE(XLST) THEN
  
   //To improve speed omit test
   //Hint: Check this 1st before calling this routine multiple times
   // when you have several similar lists
   //TMP:=MAKELIST((XLST(II)>SIZE(LST)),II,1,SIZE(XLST));//OPTIONAL TEST  
 
   //IF ΣLIST(TMP)THEN 
   // RAISE(MN+"SortByIndex",EL,SortError,ΣLIST(TMP),ListErrK); 
   //ELSE
    RETURN MAKELIST(LST(XLST(II)),II,1,SIZE(XLST));
   //END;
  END;
  RETURN {};
 END;

 EXPORT SortByKeyLST(LST,KEYLST)
 //Sort 1 LST using KEYLST. 
 //KEYLST will be sorted to determine how to sort LST
 //LST must be sortable. LOL will fail.
 //Cf: SortByKey({LST},KEYLST) 
 BEGIN
  LOCAL TMP;
  IF SIZE(LST) AND SIZE(KEYLST) THEN
   TMP:=SortN({LST,KEYLST},2);
   //Make Customisable?
   //One will match SortByKey({LST},KEYLST)
   RETURN TMP;    // {SORTEDLST,SORTEDKEYLST}
   RETURN TMP(1); // SORTEDLST 
  END;
  RETURN {};
 END;

 SortByKeyLSTS(LSTS,KEYLST)
 //Sort LSTS using KEYLST to order. 
 //KEYLST will be sorted to determine how to sort LST
 //Return: SORTEDLSTS
 //If KEYLST exists within LSTS use: SortByKeyNUM(LSTS,N)
 BEGIN
  LOCAL TMP;
  IF SIZE(LSTS) AND SIZE(KEYLST) THEN
   LSTS(0):=KEYLST;
   TMP:= SortN(LSTS,SIZE(LSTS));
   RETURN ListBEFORE(TMP,SIZE(TMP));
  END;
  RETURN {};
 END;

 SortByKeyNUM(LSTS,Keynum)
 //LSTS is {LSTV,LSTF} as returned by
 //ListCOUNTS(LST);
 //but additional fields are allowed
 //Returns {SORTED LSTS} sorted by sort key criteria
 //EG ({{1,2,3},{10,30,20}},2) -> {{2,3,1},{10,20,30}}
 BEGIN
   IF 0<Keynum≤SIZE(LSTS) THEN
    IF SIZE(LSTS(1)) AND SIZE(LSTS(Keynum)) THEN 
     //Strictly all are lists of same size
     RETURN SortN(LSTS,Keynum);
    END;
   END; 
   //Potential errors:not all checked
   //List small, not containing lists, key out of range, key list unsortable 
   RAISE(MN+"SortByKey",EL,SortError,Keynum,ListErrK); 
   RETURN {};
  //To reverse sequence call ReverseLOLS()
 END;

 EXPORT SortByKey(LSTS,KEY)
 //Sort LSTS by KEY
 //EG (LSTS,2) OR (LSTS,{6,5}) WHERE LSTS={{1,2},{3,4}}
 BEGIN
  CASE
   IF TYPE(KEY)==TYPELST THEN SortByKeyLSTS(LSTS,KEY) END;
   DEFAULT //numeric KEY param
    SortByKeyNUM(LSTS,KEY);
  END;
 END;

 EXPORT SortFromItem(LST,ITEM)
  //Return simple sort distance
  //Return LST SORTED BY NUMERICAL ABS VALUE FROM ITEM
  //Note that #integers return floats
  //=SortFromItems(LST,{ITEM})
  //ALT: USE SortByFun(LST,MYSORTFUN(LST...))
 BEGIN
  LOCAL TMP:={}; 
  IF SIZE(LST) THEN  
   TMP:=SortByFun(LST,ABS(LST-ITEM));  
  END;
  RETURN TMP;
 END;

 EXPORT SortFromItems(LST,ITEMS)
 //Sort by min sort distance from a list of items
 //#integers return floats
 //EMPTY LISTS: RETURN EMPTY LIST
 // (or: perhaps empty ITEMS should simply SORT(LST)?) 
 BEGIN
  LOCAL DX:={};
  LOCAL TMP:={{},{}}; 
  LOCAL II;
  IF SIZE(LST) AND SIZE(ITEMS) THEN 
   //IF SIZE(ITEMS)==1 THEN //OPTIONAL OPTIMISE
   // RETURN SortFromItem(LST,ITEMS(1));
   //END;
   //DX:=sort distance from nearest ITEM
   DX:=MAKELIST(MIN(ABS(LST(II)-ITEMS)),II,1,SIZE(LST));
   TMP:=SortN({LST,DX},2);  
  END;
  RETURN TMP(1);
 END;

 SortLST(LST) //ex
 //This implementation uses native SORT
 //It is convenient to export when comparing with other sorts
 BEGIN
  IF TYPE(LST)≠TYPELST THEN 
   RAISE(MN+"SortLST",EL,SortError,"",ListErrK);
   RETURN {};
  END;
  RETURN SORT(LST);
 END;

 EXPORT SortN(list,n)
 // From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
 //Call via ListSORTBYKEY to guard parameters...or call directly with good inputs 
 BEGIN
  LOCAL li,ma;
  ma:=list2mat(list) ;
  li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
  RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
 //For example:
 //SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
 //SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
 END;

 SortsVERSION() //ex
 BEGIN
  RETURN CRID;
 END;

 Pyreverse(LST) //ex
 //Python analogue
 BEGIN
  RETURN REVERSE(LST);
 END;

 EXPORT Pysort(LST,KeyFunc,RReverse)
 //Python analogue SORT
 //PyOpt KeyFunc: STRING EG "ABS" (NULL=NONE)
 //PyOpt PRReverse BOOL
 //ALT: Use SortByFun(LST,Fun(LST...))
 //Note: The Py syntax is optional fun without strings
 //Using strings here allows optional null string to be handled
 //The alt SortByFun avoids strings but requires a function
 
 BEGIN
  LOCAL TMP;
  IF KeyFunc=="" THEN
   ListANS:=SORT(LST);
   RETURN IFTE(RReverse,Pyreverse(ListANS),ListANS);
  END;
  TMP:=EXPR(KeyFunc+"(LST)");
  ListANS:=SortN({LST,TMP},2);
  RETURN IFTE(RReverse,Pyreverse(ListANS(1)),ListANS(1)); 
 END;

 ListPuzzles() //EX
 //SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
 BEGIN
  LOCAL VR;
  LOCAL LST:=MAKELIST("",VR,1,5);//40
  LST(2):="31. ListOCCURRENCESWITHSORT";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

EXPORT SortSeeAlso () //ex
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "REVERSE",
   "reverse",
   "revlist (slower)",
   "SORT",
   "sort"
   };
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;
 
 EXAMPLESORTFROM()
 //EG DISTANCE FROM FIRST AID POSTS AT 5 mile intervals along a half marathon
 BEGIN
  LOCAL ITEMS:={0,5,10};//FIRST AID POSTS
  //LOCAL LST:={10,5,−20,−5,20,−10};
  LOCAL LST:={1,2,3,4,5,6,7,8,9,10,11,12,13};
  LOCAL OUTLST;
  PRINT();
  PRINT(OUTLST:=SortFromItems(LST,ITEMS));//CLOSEST LISTED FIRST
 END;

 EXPORT SortsExamples() //ex
 //In real use, use XXX:=Sort...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(SortsVERSION);

  PRINT("Is");
  PRINT(IsSortable(0));
  PRINT(IsSortable({})); 
  PRINT(IsSortable(LL));
  PRINT(IsSortablePortable(LL));
  

  PRINT(IsSorted(LL)); 
  PRINT(IsSortedEQ(LL));
 
  PRINT("Reverse");

  PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
 
  PRINT("Sort");

  //SortByABS
  PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
 
  //SortByCounts
  PRINT(SortByCounts({1,2,3,2,3,3})); // -> {{1,2,3},{1,2,3}} 
  //SortByKey
  PRINT(SortByKeyNUM({{1,2,3},{10,30,20}},2)); //-> {{1,3,2},{10,20,30}}
  PRINT(SortByKeyNUM({{1,2,3},{1,22,3}},2));
  PRINT(ReverseLOL(SortByKeyNUM({{1,2,3},{1,22,3}},2)));

  //SortL
  PRINT(SortLST(LL));

  //SortN
  PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
  PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
  
  PRINT("Py");
  PRINT(Pyreverse({1,2,3}));
  PRINT(Pysort({1,22,3},"",0));
  PRINT(Pysort({1,22,3},"ABS",0));
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT SORTL()
 BEGIN
  LOCAL LST:={};
  ABOUT();
  //SortExamples();
   
 END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
04-27-2021, 08:08 PM
Post: #8
RE: Sort Lists API: A collection of sort functions
I have discovered that some of these are not working... Either failing at run-time, or older versions failing to compile.
Where I have had this happen before with code that used to work for me, it has sometimes been caused by a dependence in the published version on some functions present in a backup copy (which the Prime implicitly calls if the version in the latest version is renamed or out of scope), after that backup is deleted.

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
05-18-2021, 03:12 PM
Post: #9
RE: Sort Lists API: A collection of sort functions
One of the errors I am seeing is an index out of bounds error... Perhaps an index-from-0 error?

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: