RE: List API (G1CMZ): List Processing API
Version 0.02
Although there is some error detection, many routines are not robust.
Code:
LOCAL CRID:="List API V0.02 © 2017 StephenG1CMZ";
//Customise
EXPORT ListErrShow:=1;//SHOW ERRORS
//End
//Forward
ListSORT(LST);
ListREMOVEDUPLICATES(LST);
ListREMOVEX(LST,POSN);
//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";
EXPORT ListTYPE:=6;//MAGIC NUMBER FOR LISTS.Exported to avoid magic
LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)
//Also, useful temporary results
//ERR
LOCAL ListLastError:=0;
LOCAL ERRLST:={
"IndexOutofBoundsException",
"ListIsEmptyError",
"ListStatisticsError",
"Py: ItemNotFoundError",
"Py: ValueError"
};
//ERRNO IS ARBITRARY:INDEXES ERRLST
LOCAL IndexOutOfBoundsException:=1;
LOCAL ListIsEmptyError:=2;
LOCAL ListStatisticsError:=3;//
LOCAL ItemNotFoundError:=4;
LOCAL ValueError:=5;
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
END;
TBD()
BEGIN
MSGBOX( "List: TBD");
END;
EXPORT RAISE(ERR,CULPRIT,SEVERITY)
//Only exported for testing
BEGIN
IF ListErrShow AND SEVERITY THEN
MSGBOX("List: "+ERRLST(ERR)+NL+CULPRIT);
END;
ListLastError:=ERR;
END;
//MAINLY STANDARD FUNCTIONS
EXPORT ListAFTER(LST,POSN)
//Slice After POSN:POSN>0
BEGIN
LOCAL FRM:=POSN+1;
RETURN IFTE(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
BEGIN
//Guard against empty "" giving syn err
LOCAL MYNULL:=IFTE(NewValue=="","CHAR(0)",NewValue);
RETURN EXECON("IFTE(&2,&1,"+MYNULL+")",LST,LSTBOOL);
END;
EXPORT ListAPPEND(LST,ITEM)
//APPEND ITEM TO LIST
//EG L2:=APPEND(L2,3)
//PPL:L2(0):=3;
//Py:APPEND(L2,3)
BEGIN
RETURN LST(0):=ITEM;
END;
EXPORT ListBEFORE(LST,POSN)
//Slice Before POSN:
BEGIN
LOCAL TOO:=POSN-1;
IF POSN==0 THEN
RETURN ListBEFORE(LST,SIZE(POSN));
END;
RETURN IFTE(TOO>0,LST({1,TOO}),{});
END;
EXPORT ListCONCAT(LST1,LST2)
//CONCATENATE
BEGIN
CONCAT(LST1,LST2);
END;
EXPORT ListCOUNT(LST,ITEM)
//Count Instances of ITEM in LST
BEGIN
LOCAL POSN:=POS(LST,ITEM);
CASE
IF POSN==0 THEN RETURN 0; END;
//IF POSN==SIZE(LST) THEN RETURN 1; END;
DEFAULT
//FOR LISTS WIH MANY DUPLICATES:
//AN ITERATIVE SOLN WILL BE NEEDED
RETURN 1+ListCOUNT(ListAFTER(LST,POSN),ITEM);
END;
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 ListCOUNTANYDUPLICATES(LST)
//Current Implementation yields a sorted LST
//But might change
BEGIN
ListANS:=ListSORT(LST);
RETURN ListCOUNTANYDUPLICATES_SORTED(ListANS);
END;
EXPORT ListFIND(LST,ITEM)
//Find all instances of ITEM
BEGIN
LOCAL II;
LOCAL LSTPOSNS:={};
IF SIZE(LST) THEN //
//LOOP COULD BE OPTIMISED BY USING POS TO LEAP TO NEXT MODE
FOR II FROM 1 TO SIZE(LST) DO
IF LST(II)==ITEM THEN
LSTPOSNS(0):=II;
END;//IF
END;//FOR
END;//IF
//Return Positions that match ITEM
RETURN LSTPOSNS;
END;
EXPORT ListHEAD(LST)
//List HEAD AKA LISP CAR
BEGIN
RETURN LST(1);
END;
EXPORT ListINDEX(LST,ITEM)
//Simple: Return posn of item
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:
//TBD();
RETURN CONCAT(LST,ITEM);
END;
RETURN CONCAT(CONCAT(LSTB,ITEM),LSTA);
END;
EXPORT ListIsLIST(LST)
//In PPL lists and sets both 1
BEGIN
RETURN (TYPE(LST)==ListTYPE);
END;
EXPORT ListIsSET(LST)
//A uniquelist (no duplicates) may be a set
BEGIN
RETURN NOT(ListCOUNTANYDUPLICATES(LST));
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 ListMASKBOOL(LST,LSTBOOL,NewValue)
//Mask selected values
//Cf ANDBOOL
//Here 1 selects replace, not 0
BEGIN
//Guard against empty "" giving syn err
LOCAL MYNULL:=IFTE(NewValue=="","CHAR(0)",NewValue);
RETURN EXECON("IFTE(&2,"+MYNULL+",&1)",LST,LSTBOOL);
//Equivalent to
//RETURN ListANDBOOL(LST,NOT(LSTBOOL),NewValue);
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 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(ListIsEmptyError,"ListPOP",1);
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
BEGIN
RETURN suppress(LST,POSN);
END;
EXPORT ListREMOVEX(LST,POSN)
//REMOVE 1 ITEM AT POSN
BEGIN
LOCAL LSTB,LSTA;
IF POSN THEN
LSTB:=ListBEFORE(LST,POSN);
LSTA:=ListAFTER (LST,POSN);
RETURN CONCAT(LSTB,LSTA);//THIS
ELSE
//PPL: 0=Remove Last Item
RETURN ListREMOVEX(LST,SIZE(LST));
//Py: 0=RemoveFirst ie return TAIL
END;
END;
EXPORT ListREMOVE(LST,ITEM)
//Remove 1 instance of ITEM
BEGIN
LOCAL POSN:=POS(LST,ITEM);
IF POSN THEN
RETURN ListREMOVEX(LST,POSN);
END;
RAISE(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 ListSLICE(LST,FRM,TOO)
//RETURN PART OF LIST
//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,1);//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
BEGIN
RETURN SORT(LST);
END;
EXPORT ListTAIL(LST)
//List TAIL AKA LISP CDR
BEGIN
RETURN LST({2,SIZE(LST)});
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;
//STATISTICAL LIST FUNCTIONS
EXPORT ListMEAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN mean(LST);
END;
RAISE(ListIsEmptyError,"MEAN",1);
RETURN {};
END;
EXPORT ListMEAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN mean(LSTV,LSTF);
END;
RAISE(ListIsEmptyError,"MEAN",1);
RETURN {};
END;
EXPORT ListMEDIAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN(median(LST));
END;
RAISE(ListIsEmptyError,"MEDIAN",1);//(NO MEDIAN)
RETURN {};///
END;
EXPORT ListMEDIAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN(median(LSTV,LSTF));
END;
RAISE(ListIsEmptyError,"MEDIAN",1);
RETURN {};///
END;
EXPORT ListMODES2(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 ListMODES(LST)
//Get MODES of LST : Empty = Empty
BEGIN
//Make uniquelst and count
ListANS:=ListOCCURRENCES(LST);
RETURN ListMODES2(ListANS(1),ListANS(2));
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.
EXPORT Pyappend(LST,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
//ALL ITEMS FROM LST2 ARE ADDED
//=IF FULL FAIL ADDING 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(ValueError,ITEM,1);//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(ItemNotFoundError,ITEM,1);
RETURN LST;
END;
EXPORT Pyreverse (LST)
BEGIN
RETURN REVERSE(LST);
END;
EXPORT Pysort(LST,KeyFunc,RReverse)
//TBD: KeyFunc: Selects sort key from itapprox()
BEGIN
RETURN IFTE(RReverse,Pyreverse(LST),SORT(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,"Py analogues",PyFuns)
END;
EXPORT ListStatisticalFunctions()
BEGIN
LOCAL KK;
CHOOSE(KK,"Statistical Functions",
{"ListMEAN","ListMEAN2",
"ListMEDIAN","ListMEDIAN2",
"ListMODES","ListMODES2"});
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(ListBEFORE(LL,2));
//PRINT("C");
PRINT(ListCOUNT({},2));
PRINT(ListCOUNTANYDUPLICATES_SORTED({}));
PRINT(ListCOUNTANYDUPLICATES({0,2,2,2}));
//PRINT("F");
PRINT(ListFIND(LL,2));
PRINT(ListHEAD(LL));
PRINT(ListINDEX(LL,2));
PRINT(ListINSERT(LL,2,4));
PRINT(ListIsLIST(5));
PRINT(ListIsSET(LL));
PRINT(ListIsSORTED(LL));
PRINT(ListMASKBOOL({1,12},{0,1},"122"));
PRINT(ListMASKBOOL({"AA","BB"},{0,1},"CHAR(0)"));
PRINT(ListOCCURRENCES(LL));
PRINT(ListPOP(LL,2));LL:=ListANS;
PRINT(ListPOPLAST(LL));LL:=ListANS;
PRINT(ListREMOVEX(LL,2));
PRINT(ListREMOVE(LL,9));
PRINT(ListSLICE({1,2,3,4},2,3));
PRINT(ListSORT(LL));
PRINT(ListTAIL(LL));
PRINT(ListToSET({1,2,2}));
PRINT(ListMEAN(LL));
PRINT(ListMEDIAN(LL));
PRINT(ListMODES({"AC","DC"}));
PRINT("Exampled");
//RETURN ListCOUNT({1,2,2,2},2);
END;
EXPORT LIST()
BEGIN
ABOUT();
//ListExamples();
END;
Version 0.03
Code:
LOCAL CRID:="List API V0.02++ © 2017 StephenG1CMZ";
//Customise
EXPORT ListErrShow:=1;//SHOW ERRORS
//End
//Forward
ListCOUNTITEM(LST,ITEM);
ListCOUNTITEMS(LST,ITEMS);
ListREMOVEDUPLICATES(LST);
ListREMOVEX(LST,POSN);
ListSORT(LST);
//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";
EXPORT ListTYPE:=6;//MAGIC NUMBER FOR LISTS.Exported to avoid magic
LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)
//Also, useful temporary results
//ERR
LOCAL ListLastError:=0;
LOCAL ERRLST:={
"IndexOutofBoundsException",
"ListIsEmptyError",
"ListStatisticsError",
"Py: ItemNotFoundError",
"Py: ValueError"
};
//ERRNO IS ARBITRARY:INDEXES ERRLST
LOCAL IndexOutOfBoundsException:=1;
LOCAL ListIsEmptyError:=2;
LOCAL ListStatisticsError:=3;//
LOCAL ItemNotFoundError:=4;
LOCAL ValueError:=5;
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
END;
TBD()
BEGIN
MSGBOX( "List: TBD");
END;
EXPORT RAISE(ERR,CULPRIT,SEVERITY)
//Only exported for testing
BEGIN
IF ListErrShow AND SEVERITY THEN
MSGBOX("List: "+ERRLST(ERR)+NL+CULPRIT);
END;
ListLastError:=ERR;
END;
//MAINLY STANDARD FUNCTIONS
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:FASTEST
//INTERSECT IS CURRENTLY QUICKER
//BUT RECHECK AFTER ITERATIVE SOLN IMPL
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 ListCOUNTITEM(LST,ITEM)
//Count Instances of 1 ITEM in LST
//ITEM MAY BE A LIST COMPRISING 1 ITEM
//(USE COUNTITEMS TO SEARCH FOR A LIST OF ITEMS)
//NULL LST:0
//NULL ITEM:COUNTED
BEGIN
LOCAL POSN:=POS(LST,ITEM);
CASE
IF POSN==0 THEN RETURN 0; END;
//IF POSN==SIZE(LST) THEN RETURN 1; END;
DEFAULT
//FOR LISTS WIH MANY DUPLICATES:
//AN ITERATIVE SOLN WILL BE NEEDED
RETURN 1+ListCOUNT(ListAFTER(LST,POSN),ITEM);
END;
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
//THIS VERSION IS QUICKER,BUT PARAMETERS DIFFER
BEGIN
RETURN SIZE(INTERSECT(LST,ITEMS));
END;
EXPORT ListFIND(LST,ITEM)
//Find all instances of ITEM
BEGIN
LOCAL II;
LOCAL LSTPOSNS:={};
IF SIZE(LST) THEN //
//LOOP COULD BE OPTIMISED BY USING POS TO LEAP TO NEXT MODE
FOR II FROM 1 TO SIZE(LST) DO
IF LST(II)==ITEM THEN
LSTPOSNS(0):=II;
END;//IF
END;//FOR
END;//IF
//Return Positions that match ITEM
RETURN LSTPOSNS;
END;
EXPORT ListHEAD(LST)
//List HEAD AKA LISP CAR
//NULL:ERR
BEGIN
IF SIZE(LST) THEN
RETURN LST(1);
END;
RAISE(ListIsEmptyError,"HEAD",1);
RETURN {};
END;
EXPORT ListINDEX(LST,ITEM)
//Simple: Return posn of item
//
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:
//TBD();
RETURN CONCAT(LST,ITEM);
END;
RETURN CONCAT(CONCAT(LSTB,ITEM),LSTA);
END;
EXPORT ListIsLIST(LST)
//In PPL lists and sets both 1
BEGIN
RETURN (TYPE(LST)==ListTYPE);
END;
EXPORT ListIsSET(LST)
//A uniquelist (no duplicates) may be a set
BEGIN
RETURN NOT(ListCOUNTANYDUPLICATES(LST));
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 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 ListMEAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN mean(LST);
END;
RAISE(ListIsEmptyError,"MEAN",1);
RETURN {};
END;
EXPORT ListMEAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN mean(LSTV,LSTF);
END;
RAISE(ListIsEmptyError,"MEAN",1);
RETURN {};
END;
EXPORT ListMEDIAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN(median(LST));
END;
RAISE(ListIsEmptyError,"MEDIAN",1);//(NO MEDIAN)
RETURN {};///
END;
EXPORT ListMEDIAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN(median(LSTV,LSTF));
END;
RAISE(ListIsEmptyError,"MEDIAN",1);
RETURN {};///
END;
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 ListMODE(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 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(ListIsEmptyError,"ListPOP",1);
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=NUL,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
BEGIN
LOCAL LSTB,LSTA;
IF POSN THEN
LSTB:=ListBEFORE(LST,POSN);
LSTA:=ListAFTER (LST,POSN);
RETURN CONCAT(LSTB,LSTA);//THIS
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(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 ListSLICE(LST,FRM,TOO)
//RETURN PART OF LIST
//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,1);//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
BEGIN
RETURN SORT(LST);
END;
EXPORT ListTAIL(LST)
//List TAIL AKA LISP CDR
//NULL:ERR
BEGIN
IF SIZE(LST) THEN
RETURN LST({2,SIZE(LST)});
END;
RAISE(ListIsEmptyError,"TAIL",1);
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.
EXPORT Pyappend(LST,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
//ALL ITEMS FROM LST2 ARE ADDED
//=IF FULL FAIL ADDING 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(ValueError,ITEM,1);//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(ItemNotFoundError,ITEM,1);
RETURN LST;
END;
EXPORT Pyreverse (LST)
BEGIN
RETURN REVERSE(LST);
END;
EXPORT Pysort(LST,KeyFunc,RReverse)
//TBD: KeyFunc: Selects sort key from itapprox()
BEGIN
RETURN IFTE(RReverse,Pyreverse(LST),SORT(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,"Py analogues",PyFuns)
END;
EXPORT ListStatisticalFunctions()
BEGIN
LOCAL KK;
//Just listed to group these Not choosable
CHOOSE(KK,"Statistical Functions",
{"ListMEAN","ListMEAN2",
"ListMEDIAN","ListMEDIAN2",
"ListMODE","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(ListBEFORE(LL,2));
//PRINT("C");
PRINT(ListCOUNT({},2));
PRINT(ListCOUNTANYDUPLICATES_SORTED({}));
PRINT(ListCOUNTANYDUPLICATES({0,2,2,2}));
//PRINT("F");
PRINT(ListFIND(LL,2));
PRINT(ListHEAD(LL));
PRINT(ListINDEX(LL,2));
PRINT(ListINSERT(LL,2,4));
PRINT(ListIsLIST(5));
PRINT(ListIsSET(LL));
PRINT(ListIsSORTED(LL));
PRINT(ListMASKBOOL({1,12},{0,1},"122"));
PRINT(ListMASKBOOL({"AA","BB"},{0,1},"CHAR(0)"));
PRINT(ListOCCURRENCES(LL));
PRINT(ListPOP(LL,2));LL:=ListANS;
PRINT(ListPOPLAST(LL));LL:=ListANS;
PRINT(ListREMOVEX(LL,2));
PRINT(ListREMOVE(LL,9));
PRINT(ListSLICE({1,2,3,4},2,3));
PRINT(ListSORT(LL));
PRINT(ListTAIL(LL));
PRINT(ListToSET({1,2,2}));
PRINT(ListMEAN(LL));
PRINT(ListMEDIAN(LL));
PRINT(ListMODES({"AC","DC"}));
PRINT("Exampled");
//RETURN ListCOUNT({1,2,2,2},2);
END;
EXPORT LIST()
BEGIN
ABOUT();
//ListExamples();
END;
Version 0.04
Code:
LOCAL CRID:="List API V0.04 © 2017 StephenG1CMZ";
//Customise
EXPORT ListErrShow:=1;//SHOW ERRORS
//End
//Forward
ListCOUNTITEM(LST,ITEM);
ListCOUNTITEMS(LST,ITEMS);
ListREMOVEDUPLICATES(LST);
ListREMOVEX(LST,POSN);
ListSORT(LST);
//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";
EXPORT ListTYPE:=6;//MAGIC NUMBER FOR LISTS.Exported to avoid magic
LOCAL NumTYPE:=0;
LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)
//Also, useful temporary results
//ERR
LOCAL ListLastError:=0;
LOCAL ERRLST:={
"IndexOutofBoundsException",
"ListIsEmptyError",
"ListStatisticsError",
"Py: ItemNotFoundError",
"Py: ValueError"
};
//ERRNO IS ARBITRARY:INDEXES ERRLST
LOCAL IndexOutOfBoundsException:=1;
LOCAL ListIsEmptyError:=2;
LOCAL ListStatisticsError:=3;//
LOCAL ItemNotFoundError:=4;
LOCAL ValueError:=5;
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
END;
TBD()
BEGIN
MSGBOX( "List: TBD");
END;
EXPORT RAISE(ERR,CULPRIT,SEVERITY)
//Only exported for testing
BEGIN
IF ListErrShow AND SEVERITY THEN
MSGBOX("List: "+ERRLST(ERR)+NL+CULPRIT);
END;
ListLastError:=ERR;
END;
//MAINLY STANDARD FUNCTIONS
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:FASTEST
//INTERSECT IS CURRENTLY QUICKER
//BUT RECHECK AFTER ITERATIVE SOLN IMPL
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 ListCOUNTITEM(LST,ITEM)
//Count Instances of 1 ITEM in LST
//ITEM MAY BE A LIST COMPRISING 1 ITEM
//(USE COUNTITEMS TO SEARCH FOR A LIST OF ITEMS)
//NULL LST:0
//NULL ITEM:COUNTED
BEGIN
LOCAL POSN:=POS(LST,ITEM);
CASE
IF POSN==0 THEN RETURN 0; END;
//IF POSN==SIZE(LST) THEN RETURN 1; END;
DEFAULT
//FOR LISTS WIH MANY DUPLICATES:
//AN ITERATIVE SOLN WILL BE NEEDED
RETURN 1+ListCOUNT(ListAFTER(LST,POSN),ITEM);
END;
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
//THIS VERSION IS QUICKER,BUT PARAMETERS DIFFER
BEGIN
RETURN SIZE(INTERSECT(LST,ITEMS));
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(IndexOutOfBoundsException,"ListGETLIST",1);
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(ListIsEmptyError,"HEAD",1);
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;
EXPORT ListIsLIST(LST)
//BOOL:Is parameter a list
//In PPL lists and sets both 1
BEGIN
RETURN (TYPE(LST)==ListTYPE);
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 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 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 ListMEAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN mean(LST);
END;
RAISE(ListIsEmptyError,"ListMEAN",1);
RETURN {};
END;
EXPORT ListMEAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN mean(LSTV,LSTF);
END;
RAISE(ListIsEmptyError,"ListMEAN2",1);
RETURN {};
END;
EXPORT ListMEDIAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN(median(LST));
END;
RAISE(ListIsEmptyError,"ListMEDIAN",1);//(NO MEDIAN)
RETURN {};///
END;
EXPORT ListMEDIAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN(median(LSTV,LSTF));
END;
RAISE(ListIsEmptyError,"ListMEDIAN2",1);
RETURN {};///
END;
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;
//A FASTER IMPLEMENTATION OF MODE IS AT
//http://www.hpmuseum.org/forum/thread-9393.html
EXPORT ListMODE(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;
//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(ListIsEmptyError,"ListPOP",1);
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(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 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 ListSLICE(LST,FRM,TOO)
//RETURN PART OF LIST
//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,1);//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
BEGIN
RETURN SORT(LST);
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(ListIsEmptyError,"TAIL",1);
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.
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(ValueError,ITEM,1);//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(ItemNotFoundError,ITEM,1);
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)==NumTYPE AND KeyFunc==0 THEN
//0=None=NO FUNC
ELSE
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,3);//40
LST(2):="21. ListREMOVEDUPLICATES";
LST(3):="32. ListGETLIST";
CHOOSE(VR,"Puzzles",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,"Py analogues",PyFuns)
END;
EXPORT ListStatisticalFunctions()
BEGIN
LOCAL KK;
//Just listed to group these Not choosable
CHOOSE(KK,"Statistical Functions",
{"ListMEAN","ListMEAN2",
"ListMEDIAN","ListMEDIAN2",
"ListMODE","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(ListBEFORE(LL,2));
//PRINT("C");
PRINT(ListCOUNT({},2));
PRINT(ListCOUNTANYDUPLICATES_SORTED({}));
PRINT(ListCOUNTANYDUPLICATES({0,2,2,2}));
//PRINT("F");
PRINT(ListFIND(LL,2));
PRINT(ListHEAD(LL));
PRINT(ListINDEX(LL,2));
PRINT(ListINSERT(LL,2,4));
PRINT(ListIsLIST(5));
PRINT(ListIsSET(LL));
PRINT(ListIsSORTED(LL));
PRINT(ListMASKBOOL({1,12},{0,1},"122"));
PRINT(ListMASKBOOL({"AA","BB"},{0,1},"CHAR(0)"));
PRINT(ListOCCURRENCES(LL));
PRINT(ListPOP(LL,2));LL:=ListANS;
PRINT(ListPOPLAST(LL));LL:=ListANS;
PRINT(ListREMOVEX(LL,2));
PRINT(ListREMOVE(LL,9));
PRINT(ListSLICE({1,2,3,4},2,3));
PRINT(ListSORT(LL));
PRINT(ListTAIL(LL));
PRINT(ListToSET({1,2,2}));
PRINT(ListMEAN(LL));
PRINT(ListMEDIAN(LL));
PRINT(ListMODES({"AC","DC"}));
PRINT("Exampled");
//RETURN ListCOUNT({1,2,2,2},2);
END;
EXPORT LIST()
BEGIN
ABOUT();
//ListExamples();
END;
Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
|