/***************************************************************************************************************** SAS file name: fifo.sas File location: __________________________________________________________________________________________________________________ Purpose: To demonstrate the creation of FIFO queues in the SAS Data Step Author: Peter Clemmensen Creation Date: 23/05/2020 This program supports the blog post "Create a FIFO Queue in SAS with the Hash Object" on SASnrd.com *****************************************************************************************************************/ /* Richard A. Devenezias PutHash Macro */ %macro putHash (hash, vars); %* %* hash - variable that references a hash object %* vars - space separated list of variables linked to the data items of hash %* separate with pound sign (#) to get varname=varvalue format %*; %* generate a random variable name; %local random hi rc; %let random = %substr(%sysfunc(ranuni(0),10.8),3); %let hi = hi_&random; %let rc = rc_&random; %* emit DATA Step code that iterates the hash and %* puts the data items values in the log; declare hiter &hi ("&hash"); do &rc = &hi..first() by 0 while (&rc = 0); put %sysfunc(translate(&vars,=,#)); &rc = &hi..next(); end; &hi..delete(); put; %put WARNING: Values of variables &vars will change; %mend; /* A simple example */ data _null_; declare hash h (ordered : "A"); /* Ordered hash to control FIFO Queue */ h.definekey ('k'); h.definedata ('k', 'd'); h.definedone (); declare hiter hi ('h'); k = sum(k, 1); /* Queue */ d = 100; h.add (); %putHash (h, k d); /* Display content of queue in the log */ k = sum(k, 1); /* Queue */ d = 200; h.add (); %putHash (h, k d); k = sum(k, 1); /* Queue */ d = 300; h.add (); %putHash (h, k d); rc = hi.next(); /* Dequeue */ rc = hi.prev(); h.remove(); %putHash (h, k d); k = sum(k, 1); /* Queue */ d = 400; h.add (); %putHash (h, k d); rc = hi.next(); /* Dequeue */ rc = hi.prev(); h.remove(); %putHash (h, k d); run; /* A real-life example */ data market; input UB LB; datalines; 137454.23 99272.50 127407.23 92016.34 134738.07 97310.83 118503.53 85585.88 117691.52 84999.43 126468.91 91338.66 138833.30 100268.50 ;;;; run; data customers; input pay; datalines; 117605 120194 114285 92316 125917 106480 94244 127482 94744 106371 122085 100327 107315 115530 116100 100279 94117 111069 98615 115879 124773 118694 111970 118629 129623 121400 100992 129743 93083 90643 ;;;; run; data want; format UB LB pay; keep UB LB pay; if _N_=1 then do; declare hash h(ordered:'Y'); h.definekey('k'); h.definedata('k', 'pay'); h.definedone(); declare hiter hi('h'); end; do k=1 by 1 until (lr1); set customers end=lr1; h.add(); end; do until (lr2); set market end=lr2; do until (LB <= pay <= UB | rc ne 0); rc=hi.next(); end; if rc=0 then do; output; _k=k; rc=hi.last(); rc=hi.next(); rc=h.remove(key: _k); end; else do; pay=.; output; rc=hi.last(); rc=hi.next(); end; end; run;