Version 1.2 adds some new functions, but moves MEAN and some others to my new MEANS program.
Code:
LOCAL CRID:="List API V1.2 © 2018 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
//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 ListErrK:=1;
LOCAL PyErrK:=3;
EXPORT ListLastError:=0;
LOCAL ERRKIND:={"","Error","","Py Error"};
//FIX
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 ListSortError:=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)
//Only exported for testing
BEGIN
LOCAL PROGML:=Programs();
LOCAL PROGM:=PROGML(1);//NB:THE USER PROGM RUNNING, NOT THAT RAISING THE ERROR :(
IF ListShowErrors AND SEVERITY>0 THEN
MSGBOX(PROGM+":"+MN+" "+ERRKIND(SEVERITY+1)+NL+ERRLST(ERR)+NL+CULPRIT);
END;
ListLastError:=ERR;
END;
//MAINLY STANDARD FUNCTIONS
//Lowercase names are well defined (described in Wikipedia or Python Docs)
//UPPERCASE and CamelCase names are more likely to change
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 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:BUILTIN
BEGIN
CONCAT(LST1,LST2);
END;
EXPORT ListCOUNTANYDUPLICATES (LST)
//Preferred-SORTED
BEGIN
ListANS:=ListSORT(LST);
RETURN ListCOUNTANYDUPLICATES_SORTED(ListANS);
END;
EXPORT ListCOUNTANYDUPLICATES_SLOW(LST)
//Caution can be much slower but may be faster
//REAL LST NO DUPS:5s
//INT LST 8000 DUPS:0.2s
BEGIN
RETURN SIZE(LST)-SIZE(ListREMOVEDUPLICATES(LST));
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)
//Timings consistent 0.3s
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 ListCSV2LIST()
//Importing the procedure would introduce a dependency(later?)
BEGIN
MSGBOX("To parse CSV files/strings to lists use StephenG1CMZ's CSV program.\n")
END;
EXPORT ListDIFFER(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
//PPL FASTER
//See also:head()
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
//If you do want to index ITEM, use FIND.
//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 asks-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 ListMEANS()
BEGIN
MSGBOX("StephenG1CMZ's MEANS program implements several means.");
END;
EXPORT ListMEDIAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN(median(LST));
END;
RAISE(MN+"ListMEDIAN",EL,ListIsEmptyError,"",ListErrK);//(NO MEDIAN)
RETURN {};///
END;
//Query:What_error to return?
//NAN OR {} MIGHT BE THE MEDIAN VALUE
EXPORT ListMEDIAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN(median(LSTV,LSTF));
END;
RAISE(MN+"ListMEDIAN2",EL,ListIsEmptyError,"",ListErrK);
RETURN {};///
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 ListremoveCAS(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 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;
//NB replace in CAS is different
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
//NOTE 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)
//PPL FASTER
//See also:tail
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:=Pyappend(Lst,ITEM)
// Py indexes from 0 but not yet implemented
// These names are inspired by Py,
// but may never provide exact equivalents.
//Currently,0 and allindexes are PPL-like
//Thus it achieves compatability with
//PPL(0), and CAS-Python:S-Beta (like PPL, supposedly).
//but not Python
EXPORT Pyappend(LST,ITEM)
//Python analogue
//append a single item
//NB IF List prefix is dropped conflict with CAS.append (CAS.append is slower)
//NULL LST: {ITEM}
// (LST,{ITEMLST}) ADDS 1 ITEM (A LST)EG({1},{2,3}={1,{2,3}})
BEGIN
RETURN LST(0):=ITEM;
END;
EXPORT Pyclear(LST)
//Python analogue
//Py :ALSO DELETES LIST (cf CAS purge)
BEGIN
RETURN {};
END;
EXPORT Pycopy(LST)
//Python analogue
//Py: A shallow copy PPL: simple copy
BEGIN
RETURN LST;
END;
EXPORT Pycount (LST,ITEM)
//Python analogue
//Count instances of an ITEM:(WHICH MAY BE A LIST=1ITEM)
//NB do not confuse with CAS.count(Test,Lst)
BEGIN
RETURN ListCOUNTITEMS(LST,{ITEM});
END;
EXPORT Pyextend(LST,LST2)
//Python analogue
//Py :Concat items in LST2 to LST
//Query: If listfull, should we add some or none
//PPL:LST2 may be an item
BEGIN
RETURN CONCAT(LST,LST2);
END;
EXPORT Pyindex(LST,ITEM)
//Python analogue
//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)
//Python analogue
//Py :Insert ITEM before POS
BEGIN
RETURN ListINSERT(LST,POSN,ITEM);
END;
EXPORT Pypop(LST,POSN)
//Python analogue
//Py :Pop item (Posn Omit:Last)
//PPL:Posn reqd
BEGIN
IF POSN==0 THEN
TBD();
END;
RETURN ListPOP(LST,POSN);
END;
EXPORT PypopLast(LST)
//Python analogue
//Py :Pop item (Posn Omit:Last)
//PPL:Twofunctions
BEGIN
RETURN ListPOPLAST(LST);
END;
EXPORT Pyremove(LST,ITEM)
//Python analogue
//ALSO NOTE remove in CAS
//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)
//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)==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,5);//40
LST(1):="21. ListREMOVEDUPLICATES";
LST(2):="31. ListOCCURRENCESWITHSORT";
LST(3):="32. ListGETLIST";
LST(4):="40. ListREMOVEITEM";
LST(5):="41. ListCumSum";
CHOOSE(VR,MN+"Puzzles (See thread)",LST);
END;
EXPORT ListPythonAnalogues ()
BEGIN
LOCAL KK;
LOCAL PyFuns:={
"append item",
"clear list",
"copy list",
"count item instances",
"extend list by list2",
"index item in list",
"insert item before posn",
"pop item at posn from list",
"poplast",
"remove instance of item",
"reverse list",
"sort list"};
//Just Listed as a reminder:not Selectable
CHOOSE(KK,MN+"Py...",PyFuns)
END;
EXPORT ListSeeAlso ()
BEGIN
LOCAL KK;
LOCAL CatFuns:={
"append:slower",
"count",
"DIFFERENCE",
"head-slower",
"intersect-fast(AND)",
"list2mat",
"mat2list",
"prepend",
"quantile",
"quartile1",
"quartile3",
"quartiles",
"remove",
"replace",
"REVERSE",
"revlist-slower",
"suppress",
"tail:slower",
"union"};
//Just Listed as a reminder:not Selectable
CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)
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("F");
PRINT(ListFIND(LL,2));
PRINT("G");
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(ListIsSORTABLE(LL));
PRINT(ListIsSORTED(LL));
PRINT(ListIsTYPE({3.4},1-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(ListMEDIAN(LL));
PRINT(ListMODE({"AC","DC"}));
PRINT("Exampled");
//RETURN 0;
END;
//These alternative implements are slower:
//They can be removed but may be useful for testing
EXPORT Listcountanyduplicates_(LST)
//SLOWER
BEGIN
LOCAL LL:=UNION(LST);
RETURN (SIZE(LST)-SIZE(LL));
END;
EXPORT LIST()
BEGIN
ABOUT();
//ListExamples();
END;
Indexing of the Python analogues now no longer handles Index 0 in a Python manner. Indexing is now as in PPL. This should therefore be compatible with the Python syntax reported to be in the new Beta release, although I have been unable to test that myself.
Update: This version does not compile.
A couple of missing names - ListCOUNT should be ListCOUNTITEMS and ListDIFFER2 is renamed.