Hello Experts,
When I create a hash table, I have to specify the key value, but if I want to replace the key value with a new variable created during the hash iterator process within the same data step. How do I do that?
For the code below, I want the dataset work.temp1(highlighted in red) to be created before it hold by "mylittlehash1" ,how do I achieve that?
My goal is to use one single datastep (with hash) to complete the task as shown in the code below.
data work.temp1 work.temp2;
attrib filename length=$1000
sfname length=$1000
key length=$1000;
if _n_=1 then do;
declare hash mylittlehash(dataset: 'library.want', ordered:'yes');
declare hiter mylittlehashter('mylittlehash');
mylittlehash.defineData('filename');
mylittlehash.defineKey('sfname');
mylittlehash.defineDone();
call missing(filename,sfname,key);
rc=mylittlehashter.first();
do until (rc ne 0);
perlexpression2=prxparse("/\w*(\w\w\d\d\d\d)(\w)\w*/");
if prxmatch(perlexpression2,filename) then do;
Key=upcase((prxposn(perlexpression2,1,filename)));
output work.temp1;
rc=mylittlehashter.next();
end;
end;
declare hash mylittlehash1(dataset: 'work.temp1', ordered:'yes', duplicate: 'r');
mylittlehash1.defineKey('key');
mylittlehash1.defineData('key');
mylittlehash1.defineDone();
end;
set files_found;
perlexpression=prxparse("/\w*(\w\w\d\d\d\d)(\w)\w*/");
if prxmatch(perlexpression,filename) then do;
Key=upcase((prxposn(perlexpression,1,filename)));
end;
if prxposn(perlexpression,2,filename)="Z";
rc=mylittlehash1.check();
if rc=0 then output work.temp2;
run;
Thanks
Declare 2 hashes together within the "if _n_=1, then within your hiter loop instead of writing to "output work.temp1" you add the records to the 2nd hash "myhash2.add()".
Once you finished iteration through the first hash you can delete it if you want "mylittlehash1.delete()", and should you also need "work.temp1" after the data step finished then write your 2nd hash to a table "myhash2.output(dataset:"work.temp1")
Hi Patrick,
I have modified the code like below:
Is that correct?
data work.temp;
attrib filename length=$1000
sfname length=$1000
key length=$1000;
if _n_=1 then do;
declare hash mylittlehash(dataset: 'library.want(where =(_job_status="Failed"))', ordered:'yes');
declare hiter mylittlehashter('mylittlehash');
mylittlehash.defineData('filename');
mylittlehash.defineKey('sfname');
mylittlehash.defineDone();
call missing(filename,sfname,key);
declare hash mylittlehash1();
mylittlehash1.defineKey('key');
mylittlehash1.defineData('key');
mylittlehash1.defineDone();
rc=mylittlehashter.first();
do until (rc ne 0);
perlexpression2=prxparse("/\w*(\w\w\d\d\d\d)(\w)\w*/");
if prxmatch(perlexpression2,filename) then do;
Key=upcase((prxposn(perlexpression2,1,filename)));
r=mylittlehash1.add();
rc=mylittlehashter.next();
end;
end;
end;
set files_found;
perlexpression=prxparse("/\w*(\w\w\d\d\d\d)(\w)\w*/");
if prxmatch(perlexpression,filename) then do;
Key=upcase((prxposn(perlexpression,1,filename)));
end;
if prxposn(perlexpression,2,filename)="Z";
rc=mylittlehash1.check();
if rc=0 then output work.temp;
run;
Without sample data I can't check if this works in full detail - but from what I can see the code looks pretty good. I've made a few changes to your code. I've added comments where the changes were actually important and not just cosmetic.
data work.temp;
attrib filename length=$1000
sfname length=$1000
key length=$1000;
if _n_=1 then
do;
declare hash mylittlehash(dataset: 'library.want(where =(_job_status="Failed"))', ordered:'yes');
declare hiter mylittlehashter('mylittlehash');
rc=mylittlehash.defineData('filename');
rc=mylittlehash.defineKey('sfname');
rc=mylittlehash.defineDone();
declare hash mylittlehash1();
rc=mylittlehash1.defineKey('key');
rc=mylittlehash1.defineData('key');
rc=mylittlehash1.defineDone();
call missing(of _all_);
rc=mylittlehashter.first();
/* keep prxparse outside of the loop or the expression will get compiled */
/* for every single iteration of the loop (slow and cluttering memory) */
perlexpression2=prxparse("/\w*(\w\w\d\d\d\d)(\w)\w*/");
do until (rc ne 0);
if prxmatch(perlexpression2,filename) then
do;
Key=upcase((prxposn(perlexpression2,1,filename)));
r=mylittlehash1.add();
rc=mylittlehashter.next();
end;
end;
end;
set files_found;
/* same thing: compile the expression only once */
retain perlexpression;
if _n_=1 then
perlexpression=prxparse("/\w*(\w\w\d\d\d\d)(\w)\w*/");
if prxmatch(perlexpression,filename) then
do;
Key=upcase((prxposn(perlexpression,1,filename)));
end;
if prxposn(perlexpression,2,filename)="Z" then
do;
if mylittlehash1.check() = 0 then
output work.temp;
end;
run;
Thanks a lot!
Did this answer your question? If so then please mark the answer as correct.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.