Code:
// LibAssoc v0.801 - primer september 2017
#pragma mode( separator(.,;) integer(h32) )
// decl : Order List functions (OL_)
OL_SEEKI(L,V,S,E);
//find a location to add
EXPORT OL_FADD(L,V)
BEGIN
local s:= SIZE(L);
IF s==0 THEN RETURN 1; END;
RETURN OL_SEEKI(L,V,1,s);
END;
// find position from an ordered list, return 0 if not found
EXPORT OL_FIND(L,V)
BEGIN
local p:=OL_FADD(L,V);
IF p>SIZE(L) OR L(p)≠V THEN RETURN 0; END;
RETURN p;
END;
// internal function
OL_SEEKI(L,V,S,E)
BEGIN
IF S==E THEN
IF V>L(M) THEN RETURN E+1; END;
RETURN E;
END;
local M:=CEILING((S+E)/2);
IF V>L(M) THEN RETURN OL_SEEKI(L,V,M,E); END;
IF V==L(M) THEN RETURN M; END;
IF S+1==E THEN
IF V≤L(S) THEN RETURN S; END;
RETURN E;
END;
RETURN OL_SEEKI(L,V,S,M);
END;
//test with : OL_FADD({2,4,6,8,10}, 5)
//---------------------------
// Associated List
EXPORT AL_NEW()
BEGIN
RETURN {{},{}};
END;
EXPORT AL_SET(L,K,V)
BEGIN
local keys:=L_GET(L,1);
local vals:=L_GET(L,2);
local r:=AL_NEW();
local p:=OL_FADD(keys,K);
IF p≤SIZE(keys) AND keys(p)==K THEN // => modify
vals:=L_SET(vals,p,V);
r:=L_SET(r,1,keys);
r:=L_SET(r,2,vals);
RETURN r;
END;
keys:=L_INS(keys,p,K);
vals:=L_INS(vals,p,V);
r:=L_SET(r,1,keys);
r:=L_SET(r,2,vals);
RETURN r;
END;
// test :
//AL_SET(AL_NEW(), "k5", 111);
//AL_SET(Ans, "k1", 222);
//AL_SET(Ans, "k5", 999);
//search for a key, return 0 if not found, not 0 if found
EXPORT AL_FKEY(L,K)
BEGIN
RETURN OL_FIND(L_GET(L,1),K);
END;
// return the value for the given key
EXPORT AL_GET(L,K)
BEGIN
local p:=AL_FKEY(L,K);
if p==0 THEN RETURN ""; END; // no value
RETURN L_GET(L_GET(L,2),p);
END;
// return size of the AL
EXPORT AL_SIZE(L)
BEGIN
RETURN SIZE(L_GET(L,1));
END;
// remove a key from an AL
EXPORT AL_DEL(L,K)
BEGIN
local n:=AL_SIZE(L);
IF n==0 THEN RETURN L; END;
local p:=AL_FKEY(L,K);
IF p==0 THEN RETURN L; END;
local keys:=L_GET(L,1);
local vals:=L_GET(L,2);
local r:=AL_NEW();
local k2:={}, v2:={},i;
FOR i FROM 1 TO n DO
if i≠p THEN
k2:=L_INS(k2,0,keys(i));
v2:=L_INS(v2,0,vals(i));
END;
END;
r:=L_SET(r,1,k2);
r:=L_SET(r,2,v2);
RETURN r;
END;
//identify values that matchs conditions, return keys,
//a function is used to find if it match or not. return >0 for yes.
EXPORT AL_VMATCH(L,FCT)
BEGIN
local keys:=L_GET(L,1);
local n:=SIZE(keys);
IF n==0 THEN RETURN {}; END;
local vals:=L_GET(L,2);
local ret:=L_MAP(vals,FCT);
local r:={},i;
FOR i FROM 1 TO n DO
IF ret(i)>0 THEN r:=L_INS(r,0,keys(i)); END;
END;
RETURN r;
END;
// test with
//EXPORT vtest(V) //do a test...
// BEGIN
// if SIZE(V)>2 THEN RETURN 1; END;
// RETURN 0;
// END;
// AL_VMATCH({{"k1","k2","k3"},{"a","abc","abcdef"}},"vtest")
EXPORT AL_VMAP(L,FCT)
BEGIN
local keys:=L_GET(L,1);
local n:=SIZE(keys);
IF n==0 THEN RETURN L; END;
local vals:=L_GET(L,2);
local ret:=L_MAP(vals,FCT);
local r:={keys, ARR2LST(ret)};
RETURN r;
//r:= ARR2LST(ret);
END;
// AL_VMAP({{"k1","k2","k3"},{"a","abc","abcdef"}},"vtest")
EXPORT AL_FOREACH(L,FCT)
BEGIN
local keys:=L_GET(L,1);
local n:=SIZE(keys);
local vals:=L_GET(L,2);
local k,v,f,i;
FOR i FROM 1 TO n DO
k:=L_GET(keys,i);
v:=L_GET(vals,i);
IF TYPE(k)==2 THEN k:="\""+k+"\""; END;
IF TYPE(v)==2 THEN v:="\""+v+"\""; END;
f:=FCT+"("+k+","+v+")";
EVAL(EXPR(f));
END;
END;
// test with
//EXPORT disp_al(a,b)
//BEGIN
//PRINT(a+" -> "+b);
//END;
// AL_FOREACH({{1,"a"},{"test",456}},"disp_al");
EXPORT AL_SPLIT(ST,s1,k)
BEGIN
local l1:=SPLIT(ST,s1),l2;
local r:=AL_NEW();
local i,n:=SIZE(l1);
local itm:="";
FOR i FROM 1 TO n DO
itm:=L_GET(l1,i);
l2:=SPLIT(itm,k);
r:=AL_SET(r, L_GET(l2,1),L_GET(l2,2));
END;
RETURN r;
END;
// AL_SPLIT("A=123!B=abc", "!","=") : split to AL
// AL_SPLIT2("A=1,2,3!B=4,abc", "!","=",",") : split to AL with a list as values
EXPORT AL_SPLIT2(ST,s1,k,s2)
BEGIN
local l1:=SPLIT(ST,s1),l2;
local r:=AL_NEW();
local i,n:=SIZE(l1);
local itm:="";
FOR i FROM 1 TO n DO
itm:=L_GET(l1,i);
l2:=SPLIT(itm,k);
r:=AL_SET(r, L_GET(l2,1),SPLIT(L_GET(l2,2),s2));
END;
RETURN r;
END;