BookmarkSubscribeRSS Feed
gyambqt
Obsidian | Level 7

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

5 REPLIES 5
Patrick
Opal | Level 21

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

gyambqt
Obsidian | Level 7


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;

Patrick
Opal | Level 21

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;

gyambqt
Obsidian | Level 7

Thanks a lot!

Patrick
Opal | Level 21

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

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1182 views
  • 0 likes
  • 2 in conversation