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


Messages In This Thread
RE: Sort Lists API: A collection of sort functions - StephenG1CMZ - 12-03-2019 11:42 PM



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