Post Reply 
Sort Lists API: A collection of sort functions
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
Post Reply 


Messages In This Thread
RE: Sort Lists API: A collection of sort functions - StephenG1CMZ - 09-27-2018 09:19 PM



User(s) browsing this thread: 1 Guest(s)