DATA Step, Macro, Functions and more

Hash Question!

Reply
Regular Contributor
Posts: 152

Hash Question!

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

Respected Advisor
Posts: 4,173

Re: Hash Question!

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")

Regular Contributor
Posts: 152

Re: Hash Question!


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;

Respected Advisor
Posts: 4,173

Re: Hash Question!

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;

Regular Contributor
Posts: 152

Re: Hash Question!

Thanks a lot!

Respected Advisor
Posts: 4,173

Re: Hash Question!

Did this answer your question? If so then please mark the answer as correct.

Ask a Question
Discussion stats
  • 5 replies
  • 284 views
  • 0 likes
  • 2 in conversation