Search code examples
hashtablesascode-duplication

SAS - hash tables and has_next


I'm looking for an elegant solution to the below issue that will help avoid code duplication. You can see that this line:

put auction_id= potential_buyer= ;* THIS GETS REPEATED;

Gets repeated in this code:

data results;

  attrib potential_buyer length=$1;

  set auction;

  if _n_ eq 1 then do;
    declare hash ht1(dataset:'buyers', multidata: 'y');
    ht1.definekey('auction_id');
    ht1.definedata('potential_buyer');
    ht1.definedone();
    call missing (potential_buyer);
  end;


  **
  ** LOOP THROUGH EACH POTENTIAL BUYER AND PROCESS THEM
  *;
  if ht1.find() eq 0 then do;

    put auction_id= potential_buyer= ;* THIS GETS REPEATED;

    ht1.has_next(result: ht1_has_more);
    do while(ht1_has_more);
      rc = ht1.find_next();

      put auction_id= potential_buyer= ;* THIS GETS REPEATED;

      ht1.has_next(result: ht1_has_more);
    end;
  end;
run;

I've simplified the above example to a single line as the real code block is quite long and complex. I'd like to avoid using a %macro snippet or a %include if possible as I'd like to keep the logic "within" the data step.

Here's some sample data:

    data auction;
      input auction_id;
    datalines;
    111
    222
    333
    ;
    run;

    data buyers;
      input auction_id potential_buyer $;
    datalines;
    111 a
    111 c
    222 a
    222 b
    222 c
    333 d
    ;
    run;

Solution

  • I figured it out. Turned out to be pretty simple in the end just had a little trouble wrapping my brain around it:

    data results;
    
      attrib potential_buyer length=$1;
    
      set auction;
    
      if _n_ eq 1 then do;
        declare hash ht1(dataset:'buyers', multidata: 'y');
        ht1.definekey('auction_id');
        ht1.definedata('potential_buyer');
        ht1.definedone();
        call missing (potential_buyer);
      end;
    
    
      **
      ** LOOP THROUGH EACH POTENTIAL BUYER AND PROCESS THEM
      *;
      if ht1.find() eq 0 then do;
    
        keep_processing = 1;
        do while(keep_processing);
    
          put auction_id= potential_buyer= ;* THIS GETS DOESNT GET REPEATED ANYMORE =);
    
          ht1.has_next(result: keep_processing);
          rc = ht1.find_next();
        end;
      end;
    
    run;