Post Reply 
List API (G1CMZ): List Processing API
11-16-2017, 10:04 PM
Post: #4
RE: List API (G1CMZ): List Processing API
Version 1.1: Some new procedures and performance improvements, including useful contributions from the forum.

Code:


 LOCAL CRID:="List API V1.1 © 2017 StephenG1CMZ";
 LOCAL MORETEXT:="A collection of list routines brought to you by StephenG1CMZ,\n with some from the forum.";
 
 //Customise
 EXPORT ListShowErrors:=1;//SHOW ERRORS
 EXPORT ListNumericTypes:={DOM_FLOAT-1,DOM_INT-1,DOM_COMPLEX-1,DOM_MATRIX-1};
 //Query: Include COMPLEX,LONGFLOAT,MATRIX?
 EXPORT ListSortableTypes:={DOM_FLOAT-1,DOM_INT-1,3-1};//3-1=MAGIC NUMBER FOR STRINGS NOT DOM_STRING=12 NOT COMPLEX MATRIX OR LIST
  //NB To test: sort >1 item
 //End

 //Forward
 ListCOUNTANYDUPLICATES_SORTED(SORTEDLST);
 ListCOUNTITEM(LST,ITEM);
 ListCOUNTITEMS(LST,ITEMS);
 ListIsTYPE(LST,TYPES);
 ListOCCURRENCES(LST);
 ListREMOVEDUPLICATES(LST);
 ListREMOVEX(LST,POSN);
 ListSORT(LST);
 ListSORTN(LST,NN);

 //NB In main routines (ie not Python)
 //POSN parameter is >=0 (0=LAST)
 //POSN returned is ≥0 (PPL,0=NOTIN)

 //LOCAL SL:=1;
 LOCAL NL:="\n";

 LOCAL MN:="List.";//Name
 LOCAL EMPTY0:=0;//ADDITIVE
 LOCAL EMPTY1:=1;//MULTIPLICATIVE

//TO REFER TO ListTYPE, USE DOM_LIST-1; MAGIC NUMBER FOR LISTS.

 LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)
  //Also, useful temporary results 

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

 TBD()
 BEGIN
  MSGBOX(MN+"TBD");
 END;
 
 EXPORT RAISE(MN,ERRLST,ERR,CULPRIT,SEVERITY)
 //Only exported for testing
 BEGIN
  IF ListShowErrors AND SEVERITY>0 THEN
   MSGBOX(MN+" "+ERRKIND(SEVERITY+1)+NL+EL(ERR)+NL+CULPRIT);
  END;
  ListLastError:=ERR;
 END;

 NAN()
 BEGIN
  RETURN NaN;
 END;

 //MAINLY STANDARD FUNCTIONS

 EXPORT ListΣLIST(LST)
 BEGIN
  RETURN IFTE(SIZE(LST),ΣLIST(LST),EMPTY0); 
 END;

 EXPORT ListΠLIST(LST)
 BEGIN
  LOCAL SZ:=SIZE(LST);
  
  IF SZ>1 THEN RETURN ΠLIST(LST);
  END;
  IF SZ==1 THEN RETURN LST(1);
  END;
  //IF SZ==0 THEN
  RETURN EMPTY1;
  //END;
 END;

 EXPORT ListAFTER(LST,POSN)
 //Slice After POSN:
 //POSN=0 OR LAST:{}
 BEGIN
  LOCAL FRM:=POSN+1;
  RETURN IFTE((POSN==0 OR FRM>SIZE(LST)),{},LST({FRM,SIZE(LST)}));
 END;

 EXPORT ListANDBOOL(LST,LSTBOOL,NewValue)
 //Replace items ANDed out with NULL(NewValue)
 //EG ({"AA","BB"},{0,1},"CHAR(0)") = {"","BB"}//Note the quotes
 //EG ({11,13},{0,1},"12")//NOMORETHAN12
 //RequirementSpec:
 //http://www.hpmuseum.org/forum/thread-5092.html
 //Usage:
 //http://www.hpmuseum.org/forum/thread-5031.html
 //See also:MaskBOOL
 //NULL=NULL
 BEGIN
  //Guard against empty "" giving syn err
  LOCAL MYNULL:=IFTE(NewValue=="","CHAR(0)",NewValue);
  IF SIZE(LST) AND SIZE(LSTBOOL) THEN
   RETURN EXECON("IFTE(&2,&1,"+MYNULL+")",LST,LSTBOOL);
  END;
  RETURN {};
 END;

 EXPORT ListAPPEND(LST,ITEM)
 //APPEND ITEM TO LIST
 //EG L2:=APPEND(L2,3)
 //PPL:L2(0):=3;
 //Py:APPEND(L2,3)
 //NULL: {ITEM}
 // (LST,{ITEMLST}) ADDS 1 ITEM (A LST)
 BEGIN
  RETURN LST(0):=ITEM; 
 END;

 EXPORT ListBEFORE(LST,POSN)
 //Slice Before POSN: 
 //POSN=0: ({1,2},0)={1}
 BEGIN
  LOCAL TOO:=POSN-1;
  IF POSN==0 THEN
    RETURN ListBEFORE(LST,SIZE(LST));
  END;
  RETURN IFTE(TOO>0,LST({1,TOO}),{});
 END;

 EXPORT ListCONCAT(LST1,LST2)
 //CONCATENATE
 BEGIN
  CONCAT(LST1,LST2);
 END;

 EXPORT ListCOUNT (LST,ITEM)
 //COUNT 1 ITEM:(WHICH MAY BE A LIST)
 BEGIN  
  RETURN ListCOUNTITEMS(LST,{ITEM});
 END;

 EXPORT ListCOUNTANYDUPLICATES(LST)
 //Current Implementation yields a sorted LST
 //But might change
 BEGIN
  ListANS:=ListSORT(LST);
  RETURN ListCOUNTANYDUPLICATES_SORTED(ListANS);
 END;

 EXPORT ListCOUNTANYDUPLICATES_SORTED(SortedLST)
 //Count how many duplicates in a sortedlist,Return a REAL INT
 //({1,9,9}=1 dup, {1,2,2,3,3,3}=3 dup)
 BEGIN
  LOCAL II;
  LOCAL DUPCOUNT:=0;
  IF SIZE(SortedLST)>1 THEN
   FOR II FROM 1 TO SIZE(SortedLST)-1 DO
    IF SortedLST(II) ==SortedLST(II+1) THEN
     DUPCOUNT:=DUPCOUNT+1;
    END;//IF
   END;//FOR
   //ELSE:SMALL LISTS HAVE NO DUPLICATES
  END;//IF
  RETURN DUPCOUNT;
 END;

 EXPORT ListCOUNTITEMS(LST,ITEMS)
 //ITEMS MAY BE 1 ITEM OR A LIST OF SEPARATE ITEMS
 //SO TO COUNT LISTS, CONTAIN THEM IN A LIST
 //EG {1,{},2},{{}}= 1
 //EG {1,2,3},{2,3} = 2
 //EG {1,{2,3}},{2,3} = 0 (TO SEARCH FOR ITEM {2,3} USE COUNT)
 //ITEMS NULL=0
 //LST NULL=0
 BEGIN
  RETURN SIZE(INTERSECT(LST,ITEMS));
 END;
 
 EXPORT ListDIFFER2(LST1,LST2)
 //POSITION OF 1st DIFFERENCE
 //FLOAT≠INTEGER
 //SIZE≠SIZE: SZ+1 RETURNED(UNLESS EARLIER DIFFERENCE)
 BEGIN
  LOCAL II:=1;
  LOCAL SZ:=MIN(SIZE(LST1),SIZE(LST2));

  IF EQ(LST1,LST2) THEN
   RETURN 0;
  END;
  //IF SIZE(LST1)≠SIZE(LST2) THEN
  // RETURN −1;
  //END;
  WHILE II≤SZ DO
   IF TYPE(LST1)≠TYPE(LST2) OR LST1(II)≠LST2(II) THEN
    RETURN II;
   END;
   II:=II+1;
  END; 
  RETURN IFTE(SIZE(LST1)>SZ OR SIZE(LST2)>SZ,SZ+1,0);
 END;

 EXPORT ListFIND(LST,ITEM)
  //See http://www.hpmuseum.org/forum/thread-9431.html
 BEGIN 
  LOCAL X,Y;
  LOCAL LSTPOSNS={};

  WHILE X:=POS(LST,ITEM) DO
    LSTPOSNS(0):=(Y:=X+Y);
    LST:=LST({X,SIZE(LST)}+1)
  END;
  RETURN LSTPOSNS;
 END;
 
 EXPORT ListGETLIST(LST,GETLST)
 //Solves Puzzle #32. POSN≥0.
 //POSN>SIZE(LST):EXCEPTION. RETURN {} FOR THAT ITEM
 BEGIN
 LOCAL II;

  IF SIZE(GETLST) THEN
   IF MAX(GETLST)>SIZE(LST) THEN
    RAISE(MN+"ListGETLIST",EL,IndexOutOfBoundsException,MAX(GETLST)+">"+SIZE(LST),ListErrK);
   END;
   //IFTE GUARDS INDEX>SIZE(LST)
   RETURN MAKELIST(IFTE(GETLST(II)>SIZE(LST),{},LST(GETLST(II))),II,1,SIZE(GETLST));
  END;
  RETURN {};//ASKED TO GET NOTHING
 END;

 EXPORT ListHEAD(LST)
 //List HEAD AKA LISP CAR
 //NULL:ERR
 BEGIN
  IF SIZE(LST) THEN
   RETURN LST(1);
  END;
  RAISE(MN+"ListHEAD",EL,ListIsEmptyError,"",ListErrK);
  RETURN {};
 END;

 EXPORT ListINDEX(LST,ITEM)
 //Despite the confusing name
 //Simple: Return posn of 1st instance of item
 //NULL: 0
 BEGIN
  RETURN POS(LST,ITEM);
 END;

 EXPORT ListINSERT(LST,POSN,ITEM)
 //INSERT ITEM BEFORE POSN
 //PPL POSN=0 = APPEND
 //Py  POSN=0 = 1ST
 BEGIN
  LOCAL POSNB:=POSN-1;
  LOCAL LSTB:=IFTE(POSN==1,{},LST({1,POSNB}));
  LOCAL LSTA:=LST({POSN,SIZE(LST)});

  IF POSN==0 THEN //IN PPL:
   //IT IS UNCLEAR WHETHER THIS SHOULD APPEND,
   //OR INSERT BEFORE LAST 
   //OPINIONS?
   //TBD();
   RETURN CONCAT(LST,ITEM);
  END;
  RETURN CONCAT(CONCAT(LSTB,ITEM),LSTA);
 END;

 //Query:
 //IsLIST ask-Is parameter this
 //IsNUMERIC,IsSET,IsSORTABLE,IsTYPE ask:Are contents this
 //Change names to clarify?

 EXPORT ListIsLIST(LST)
 //BOOL:Is actual parameter a list_type
 //In PPL lists and sets both 1
 //To check instead that a list contains only lists,
 //use IsTYPE(LST,{DOM_LIST})
 BEGIN
   RETURN (TYPE(LST)==DOM_LIST-1);
 END;

 EXPORT ListIsNUMERIC(LST)
 //Is list currently numeric
 BEGIN 
  RETURN ListIsTYPE(LST,ListNumericTypes);
 END;

 EXPORT ListIsSET(LST)
 //BOOL:Is LST currently a set (no duplicates)
 //A uniquelist (no duplicates) may be a set
 //NULL:1
 BEGIN
  RETURN NOT(ListCOUNTANYDUPLICATES(LST));
 END;

 EXPORT ListIsSORTABLE(LST)
 //0.Is parameter a list
 //1.Is TYPE of contents OF ORDERABLE DATA
 //2.Is ListSORT 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

 BEGIN
  IF TYPE(LST)==DOM_LIST-1 THEN
   RETURN ListIsTYPE(LST,ListSortableTypes);
  END;
  RETURN 0;//NO LIST:CANNOT BE SORTED
 END;

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

 EXPORT ListIsTYPE(LST,TYPES)
 //TYPES: TYPE OR LIST OF TYPES
 //SEE ALSO:IsNUMERIC
 //MAKELIST IS FASTER THAN [FOR,INCREMENT COUNT] 
 BEGIN
  LOCAL II;

  IF TYPE(TYPES)==DOM_FLOAT-1 THEN RETURN ListIsTYPE(LST,{TYPES});
  END;
 
  IF SIZE(LST) AND SIZE(TYPES) THEN
   ListANS:=MAKELIST(IFTE(POS(TYPES,TYPE(LST(II))),1,0),II,1,SIZE(LST));//List matching types
   RETURN IFTE(ΣLIST(ListANS)==SIZE(LST),1,0); //Count them
  END;
  RAISE(MN+"ListIsTYPE",EL,ListIsEmptyError,"",1);
  //EMPTY LST: LST ALWAYS INDETERMINATE (GUARD) 
  //EMPTY TYPES: 0>NO MATCHES OR 1>NO REJECTS 
  RETURN 0;//INDETERMINATE
 END;

 EXPORT ListMASKBOOL(LST,LSTBOOL,NewValue)
 //Mask selected values
 //Cf ANDBOOL
 //Here 1 selects replace, not 0
 //NULL=NULL
 BEGIN 
  //Guard against empty "" giving syn err
  LOCAL MYNULL:=IFTE(NewValue=="","CHAR(0)",NewValue);
  IF SIZE(LST) AND SIZE(LSTBOOL) THEN
   RETURN EXECON("IFTE(&2,"+MYNULL+",&1)",LST,LSTBOOL);
  END;
  RETURN {};
  //Equivalent to
  //RETURN ListANDBOOL(LST,NOT(LSTBOOL),NewValue);
 END;

EXPORT ListMAX(LST)
BEGIN
  RETURN IFTE(SIZE(LST),MAX(LST),EMPTY0);
END;

 EXPORT ListMEAN(LST)
 BEGIN
  IF SIZE(LST) THEN
   RETURN (mean(LST));
  END;
  RAISE(MN+"ListMEAN",EL,ListIsEmptyError,"",ListErrK);
  RETURN NAN();
 END;
 //NB MEAN AND MEAN2 CURRENTLY RETURN TYPE RAT
 //USE approx if you prefer real
 EXPORT ListMEAN2(LSTV,LSTF)
 BEGIN
  IF SIZE(LSTV) AND SIZE(LSTF) THEN
   RETURN (mean(LSTV,LSTF));
  END;
  RAISE(MN+"ListMEAN2",EL,ListIsEmptyError,"",ListErrK);
  RETURN NAN();
 END;

 EXPORT ListMEDIAN(LST)
 BEGIN
  IF SIZE(LST) THEN
   RETURN(median(LST));
  END;
  RAISE(MN+"ListMEDIAN",EL,ListIsEmptyError,"",ListErrK);//(NO MEDIAN)
  RETURN NAN();///
 END;

 EXPORT ListMEDIAN2(LSTV,LSTF)
 BEGIN
  IF SIZE(LSTV) AND SIZE(LSTF) THEN
   RETURN(median(LSTV,LSTF));
  END;
  RAISE(MN+"ListMEDIAN2",EL,ListIsEmptyError,"",ListErrK);
  RETURN NAN();///
 END;

 EXPORT ListMIN(LST)
 BEGIN
  RETURN IFTE(SIZE(LST),MIN(LST),EMPTY0);
 END;

 EXPORT ListMODE(L)
 //From http://www.hpmuseum.org/forum/thread-9393.html
 BEGIN
 LOCAL l1,l2;
 l1:=UNION(L);
 l2:=MAKELIST(SIZE(INTERSECT(L,l1(I))),I,1,SIZE(l1));
 l2:=(l2==MAX(l2))*MAKELIST(I,I,1,SIZE(l1));
 l2:=remove(0,l2);
 MAKELIST(l1(l2(I)),I,1,SIZE(l2));
END;
   
 //MODE1_DEPRECATED is deprecated as it is slower
 //MODE2 is likely slower too,
 //but may be useful as parameters differ
 //(retain for comparisons speed and testing)    

 EXPORT ListMODE2(LSTV,LSTF)
 //Get MODES of ItemXFrequency Lists
 //Empty=Empty
 BEGIN
  LOCAL II;
  LOCAL MODESLST:={};
  LOCAL MODEPOSNS:={};

  IF SIZE(LSTF) AND SIZE(LSTV) THEN
   //Find MODES
   MODEPOSNS:=ListFIND(LSTF,MAX(LSTF));
  
   FOR II FROM 1 TO SIZE(MODEPOSNS) DO
    MODESLST(II):=LSTV(MODEPOSNS(II));
   END;//FOR
  END;//IF
  RETURN MODESLST;
 END;

 EXPORT ListMODE1_DEPRECATED(LST)
 //Get MODES of LST : Empty = Empty
 BEGIN
  //Make uniquelst and count
  ListANS:=ListOCCURRENCES(LST);
  
  RETURN ListMODE2(ListANS(1),ListANS(2));
 END;

 EXPORT ListOCCURRENCES(LST)
 //Given a list
 //Return unique list of occurrences and their occurrence counts as 2 lists
 BEGIN
  LOCAL II;
  LOCAL LSTF:={};
  LOCAL LSTV:=ListREMOVEDUPLICATES(LST);

  FOR II FROM 1 TO SIZE(LSTV) DO
   LSTF(II):=ListCOUNT(LST,LSTV(II));
  END;
  RETURN {LSTV,LSTF};
 END;

 EXPORT ListOCCURRENCESWITHSORT(LST)
 //As OCCURRENCES but the LSTV output is sorted
 //Puzzle #31
 //This trivial implement is quicker than sorting output lists using SORTN
 //(but using SORTN makes selecting sorting by list2 easier)
 //See also: ListSORTBYOCCURRENCES
 BEGIN
  RETURN ListOCCURRENCES(ListSORT(LST));
 END;

//There must be a better name
 EXPORT ListInvOCCUR(LSTV,LSTF)
 //INVERSE OF OCCURRENCES
 //Given V and F yield V,F times
 //NULL=NULL
 //In an OCCURRENCES list V is unique and F>0
 //But We handle V with F=0 and V nonunique
 BEGIN
  LOCAL II,JJ;
  LOCAL LST:={};

  FOR II FROM 1 TO SIZE(LSTV) DO
   IF LSTF(II) THEN //V WITH F>0
    LST:=CONCAT(LST,MAKELIST(LSTV(II),JJ,1,LSTF(II)));
   END;
  END;
 
  RETURN LST;
 END;

 EXPORT ListPOP(LST,POSN)
 //POP POSN OFF LIST
 BEGIN
  LOCAL ITEM;
  IF SIZE(LST) THEN
   ITEM:=LST(IFTE(POSN,POSN,SIZE(LST)));//0=>LAST
   ListANS:=ListREMOVEX(LST,POSN);
  ELSE
   RAISE(MN+"ListPOP",EL,ListIsEmptyError,"",ListErrK);
   ITEM:={};
   ListANS:={};
  END;   
  //RETURN POPPED ITEM
  //BUT ALSO SAVE SHORTENED LST
  RETURN ITEM;
 END;

 EXPORT ListPOPLAST(LST)
 //POP POSN OFF LIST
 //Py: POP()
 BEGIN
  RETURN ListPOP(LST,SIZE(LST)); 
 END;

 EXPORT ListremoveX(LST,POSN)
 // CAS ALTERNATIVE TO REMOVEX:MAY BE SLOW
 //See 
 //http://www.hpmuseum.org/forum/thread-9406.html and
 //http://www.hpmuseum.org/forum/thread-7987.html?highlight=suppress 
 //NULL=NULL,POSN>SZE=LST
 BEGIN
  IF POSN THEN
   RETURN suppress(LST,POSN);
  END;
  RETURN suppress(LST,SIZE(LST));//0=LAST
 END;

 EXPORT ListREMOVEX(LST,POSN)
 //REMOVE 1 ITEM AT POSN
 //NULL=NULL,POSN>SIZE=LST (NOWT REMOVED)
 BEGIN
  LOCAL LSTB,LSTA;

  IF POSN THEN
   LSTB:=ListBEFORE(LST,POSN);
   LSTA:=ListAFTER (LST,POSN);
   RETURN CONCAT(LSTB,LSTA);
  ELSE
   //PPL: 0=Remove Last Item
   RETURN ListREMOVEX(LST,SIZE(LST));
   //Py: 0=RemoveFirst ie return TAIL
  END;
 END;
 
 EXPORT Listremove(LST,ITEM) 
 //CAS version slower
 //NULL=NULL
 BEGIN
  RETURN remove(ITEM,LST);
 END;

 EXPORT ListREMOVE(LST,ITEM)
 //Remove 1 instance of ITEM
 //NULL=NULL 
 BEGIN
  LOCAL POSN:=POS(LST,ITEM);
  IF POSN THEN
   RETURN ListREMOVEX(LST,POSN);
  END;
  RAISE(MN+"ListREMOVE",EL,ItemNotFoundError,ITEM,0);
  RETURN LST;//NOTHING TO REMOVE
 END;

 EXPORT ListREMOVEDUPLICATES(LST)
 //RESULT WITH DUPLICATES JUST ONCE 
 //Native: Sequence NOT determined but seems same
 //From #21
 BEGIN
  RETURN UNION(LST);
 END;

 EXPORT ListREMOVEDUPLICATESSL(LST)
 //SL
 //My own implementation ensures known list sequence (per original LST)
 BEGIN
  LOCAL II;
  LOCAL ListANS:={};

  FOR II FROM 1 TO SIZE(LST)  DO
   IF POS(ListANS,LST(II))==0 THEN //NOT YET LISTED
    ListANS(0):=LST(II);//ADD ENTRY
   END;
  END;
  RETURN ListANS;//EACH ITEM ONCE
 END;

 EXPORT ListREMOVEITEM(LST,ITEM)
 //ALL INSTANCES.PUZZLE #40.
 BEGIN
  LOCAL II;
  LOCAL FOUND:=ListFIND(LST,ITEM);
  IF SIZE(FOUND) THEN
   ListANS:=LST;
   //Remove from right:earlier posns unchanged
   FOR II FROM SIZE(FOUND) DOWNTO 1 DO
    ListANS:=ListREMOVEX(ListANS,FOUND(II));
   END;
   RETURN ListANS;
  END;//IF
  RETURN LST;//NOTHING REMOVED 
 END;

 EXPORT ListREPLACE(LST,ITEM,ITEM2)
 //Replace instances of ITEM with ITEM2
 BEGIN
  LOCAL II;
  LOCAL FOUND:=ListFIND(LST,ITEM);
  IF SIZE(FOUND) THEN
   ListANS:=LST;
   FOR II FROM 1  TO SIZE(FOUND)  DO
    ListANS(FOUND(II)):=ITEM2;
   END;
  ELSE
   RETURN LST;
  END;
  RETURN ListANS; 
 END;

 EXPORT ListSHUFFLE(LST_NUM)
 //SHUFFLE NUM: SHUFFLE 1..N INDEXES 
 //SHUFFLE LST: SHUFFLE LST
 //N<0:GUARD:UNSHUFFLED INDEX
 //NULL OR 0 OR >10000: NULL 
 BEGIN
  LOCAL II,NUM;
  IF TYPE(LST_NUM)=DOM_FLOAT-1 THEN
   NUM:=IFTE(LST_NUM>10000,0,LST_NUM);
   IF LST_NUM<0 THEN //GUARD NEGATIVES (AVOID CRASH)
    RETURN MAKELIST(II,II,1,ABS(NUM));//UNSHUFFLED
   END;
  END;
  RETURN mat2list(randperm(LST_NUM));
 END;

 EXPORT ListSLICE(LST,FRM,TOO)
 //RETURN PART OF LIST (AKA SUB)
 //SYNTAX HINT
 //SUGGEST ALSO IMPL (LST,{2,[3]})
 //FRM≤TOO:Bad Inputs={}
 BEGIN
  LOCAL TTOO:=IFTE(TOO==0,SIZE(LST),TOO); //TO 0==LAST
  LOCAL TFRM:=IFTE(FRM==0,SIZE(LST),FRM); //FRM 0==LAST
  //MSGBOX("SLICE "+{FRM,TOO});
  IF TFRM>TTOO THEN
    //RAISE(IndexOutOfBoundsException,FRM,ListErrK);//Maybe a new error
    RETURN {};
  END; 
  RETURN LST({TFRM,TTOO});
 END;

 EXPORT ListSORT(LST)
 //This implementation uses native SORT
 //On old compilers See known bugs 
 //This will not affect MODE other than changing ordering 
 //Native SORT falls over:Use IsSORTABLE to check 1st
 //NOTET TO DEVELOPERS:
 //NB1:Sorting a list of size 1 is trivial, so test using 2to see if a t 
 BEGIN
  IF TYPE(LST)≠DOM_LIST-1 THEN 
   RAISE(MN+"ListSORT",EL,ListSortError,"",ListErrK);
  END;
  RETURN SORT(LST);
 END;

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

 EXPORT ListSORTN(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 ListSORTBYOCCURRENCES(LST)
 //reverse so most popular is 1st and index is approx rank 
 BEGIN
  ListANS:=ListOCCURRENCES(LST);
  RETURN REVERSE(ListSORTBYKEY(ListANS,2));
 END;

 EXPORT ListTAIL(LST)
 //List TAIL AKA LISP CDR
 //NULL:ERR
 //(SOME USE TAIL=LAST NOT TAIL=CDR)
 BEGIN
  IF SIZE(LST) THEN
   RETURN LST({2,SIZE(LST)});
  END;
  RAISE(MN+"ListTAIL",EL,ListIsEmptyError,"",ListErrK);
  RETURN {};
 END;

 EXPORT ListToSET(LST)
 //In addition to making the list like a set
 //wibni we could track those tnat ARE sets
 BEGIN
  RETURN ListREMOVEDUPLICATES(LST);
 END;

 EXPORT ListVERSION()
 BEGIN
  RETURN CRID;
 END;

 // Python names(LC) prefixed Py ()
 // Py  syntax: Lst.append(ITEM) etc 
 // PPL syntax: Lst:=append(Lst,ITEM)
 // Py indexes from 0 but not yet implemented
 // These names are inspired by Py, 
 // but will never provide exact equivalents.
 
 //Currently,0 is Py-like but other indexes are not.
 //Thus it achieves incompatability with 
 //PPL(0), Python (≠0) and CAS-Python:S-Beta (like PPL, supposedly).
 //Indexing is therefore likely to change here.

 EXPORT Pyappend(LST,ITEM)
 //append a single item
 BEGIN 
  RETURN append(LST,ITEM);//CAS
 END;

 EXPORT Pyclear(LST)
 //Py :ALSO DELETES LIST (cf CAS purge)
 BEGIN 
  RETURN {};
 END;

 EXPORT Pycopy(LST)
 //Py: A shallow copy PPL: simple copy
 BEGIN
  RETURN LST;
 END;

 EXPORT Pycount(LST,ITEM)
 //Py :Count occurences of item
 BEGIN
  RETURN ListCOUNT(LST,ITEM);
 END;

 EXPORT Pyextend(LST,LST2)
 //Py :Concat items in LST2 to LST
 //Query: If listfull, should we add some or none
 //PPL:LST2 may be an item 
 BEGIN
  CONCAT(LST,LST2);
 END;

 EXPORT Pyindex(LST,ITEM)
 //Py :Return index (or ValueErr)

 //TBD START:END LIMIT RANGE SEARCHED WITHOUT CHANGING INDEX
 BEGIN
  LOCAL LX:=ListINDEX(LST,ITEM); 
  IF LX==0 THEN
   RAISE(MN+"Pyindex",EL,ValueError,ITEM,PyErrK);//Py:NotFound => an error
  END;
  RETURN LX; 
 END;

 EXPORT Pyinsert(LST,POSN,ITEM)
 //Py :Insert ITEM before POS
 BEGIN
  IF POSN==0 THEN
   TBD();
   CONCAT(ITEM,LST);//Py 0
  END;
  RETURN ListINSERT(LST,POSN,ITEM); 
 END;

 EXPORT Pypop(LST,POSN)
 //Py :Pop item (Posn Omit:Last)
 //PPL:Posn reqd
 BEGIN
  IF POSN==0 THEN
   TBD();
  END;
  RETURN ListPOP(LST,POSN);
 END;

 EXPORT PypopLast(LST)
 //Py :Pop item (Posn Omit:Last)
 //PPL:Twofunctions
 BEGIN
  RETURN ListPOPLAST(LST);
 END;

 EXPORT Pyremove(LST,ITEM)
 //Py :Remove 1st ITEM,ERR IF NONE
 BEGIN
  LOCAL POSN:=POS(LST,ITEM);
  IF POSN THEN
   RETURN ListREMOVEX(LST,POSN);
  END;
  //ELSE NOTHING TO REMOVE
  RAISE(MN+"Pyremove",EL,ItemNotFoundError,ITEM,PyErrK);
  RETURN LST;
 END;
 
 EXPORT Pyreverse (LST)
 BEGIN
  RETURN REVERSE(LST);
 END;

 EXPORT Pysort(LST,KeyFunc,RReverse)
 //TBD: KeyFunc: Selects sort key from itapprox()
 BEGIN
  IF TYPE(KeyFunc)==DOM_FLOAT-1 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,4);//40
  LST(1):="21. ListREMOVEDUPLICATES";
  LST(2):="31. ListOCCURRENCESWITHSORT";
  LST(3):="32. ListGETLIST";
  LST(4):="40. ListREMOVEITEM";
  CHOOSE(VR,MN+"Puzzles (See thread)",LST);
 END;

 EXPORT ListPythonAnalogues ()
 BEGIN
  LOCAL KK;
  LOCAL PyFuns:={"Pyappend",
   "Pyclear","Pycopy","Pycount",
   "Pyextend",
   "Pyindex","Pyinsert",
   "Pypop","Pypoplast",
   "Pyremove","Pyreverse",
   "Pysort"};
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Py analogues",PyFuns)

 END;

 EXPORT ListStatisticalFunctions()
 BEGIN
  LOCAL KK;
  //Just listed to group these Not choosable
  CHOOSE(KK,MN+" Statistical Functions",
   {"ListMEAN","ListMEAN2",
    "ListMEDIAN","ListMEDIAN2",
    "ListMODE","ListMODE1_DEPRECATED","ListMODE2"});
 END;

 EXPORT ListExamples()
 //In real use, use XXX:=List...()
 BEGIN
  LOCAL LL:={1,2,3,4,5,6,7,8,9};
  PRINT();
  PRINT(ListVERSION);
  PRINT("A");
  PRINT(ListAFTER(LL,2));
  PRINT(ListANDBOOL({1,12},{0,1},"122"));
  PRINT(ListANDBOOL({"AA","BB"},{0,1},"CHAR(0)"));
  PRINT("B");
  PRINT(ListBEFORE(LL,2));
  PRINT("C");
  PRINT(ListCOUNT({},2));
  PRINT(ListCOUNTANYDUPLICATES_SORTED({}));
  PRINT(ListCOUNTANYDUPLICATES({0,2,2,2}));
  PRINT(ListCOUNTITEMS(LL,{2,3}));
  PRINT("D");
  PRINT(ListDIFFER2(LL,CONCAT(LL,2)));
  PRINT("FG");
  PRINT(ListFIND(LL,2));
  PRINT(ListGETLIST(LL,{5,3}));
  PRINT("HI");
  PRINT(ListHEAD(LL));
  PRINT(ListINDEX(LL,2));
  PRINT(ListINSERT(LL,2,4));
  PRINT("Is");
  PRINT(ListIsLIST(5));
  PRINT(ListIsNUMERIC({1,2,#3}));
  PRINT(ListIsSET(LL));
  PRINT(ListIsSORTED(LL)); 
  PRINT(ListIsTYPE({"SI"},DOM_STRING-1));
  PRINT("MNO");
  PRINT(ListMASKBOOL({1,12},{0,1},"122"));
  PRINT(ListMASKBOOL({"AA","BB"},{0,1},"CHAR(0)"));
  PRINT(ListOCCURRENCES(LL));
  PRINT("P");
  PRINT(ListPOP(LL,2));LL:=ListANS;
  PRINT(ListPOPLAST(LL));LL:=ListANS;
  PRINT("R");
  PRINT(ListREMOVEX(LL,2));
  PRINT(ListREMOVE(LL,9));
  PRINT("S");
  PRINT(ListSHUFFLE(−52));
  PRINT(ListSHUFFLE(52));
  PRINT(ListSHUFFLE({"R","G","B"}));
  PRINT(ListSLICE({1,2,3,4},2,3));
  PRINT(ListSORT(LL));
  PRINT("T");
  PRINT(ListTAIL(LL));
  PRINT(ListToSET({1,2,2}));
  PRINT("STATS");
  PRINT(ListMEAN(LL));
  PRINT(ListMEDIAN(LL));
  PRINT(ListMODE({"AC","DC"})); 
 
  PRINT("Exampled");
  //RETURN 0; 
 END;

 EXPORT LIST()
 BEGIN
  ABOUT();
  //ListExamples();
 END;

Note that the indexing used in the Python analogues included here is not currently compatible with PPL (0-index), with Python (indexing from 0), or with the Python-syntax in CAS that may be in the current Beta (PPL-like, apparrently, though I have not yet had the opportunity to verify). So it may well change in future releases.

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: List API (G1CMZ): List Processing API - StephenG1CMZ - 11-16-2017 10:04 PM



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