Last week, I introduced the SAS hash iterator object in the post An Introduction to the Hash Iterator Object. I introduce the iterator object and how to visualize it. Furthermore, I demonstrate how to declare and instantiate it. However, I do not focus much on how to use it. I do not focus on the methods we call on the iterator object. Today, I devote the post to the five hash iterator methods. These are the First, Last, Next, Prev and Setcur Methods.
In the examples to come, I will use the following data set
data have; input key data; datalines; 1 10 1 20 2 30 2 40 2 50 3 60 3 70 ;
First and Last Method
First off, let us look at the First Method(). I declare a hash object and associate an iterator object to it. For demonstration purposes, I use the Ordered:Y argument tag. That way, we can easier see how the methods work. Now, I call the First() Method. This makes the iterator object point to the logically first element in the hash object and copies the data values into the PDV. You can verify that the data values are copied into the PDV in the following PUT Statement. SAS prints key=1 data=10 in the log.
Next, let us examine the Last Method(). I call Last() in the same data step. If you examine the log, you see that the SAS hash iterator points to the logically last element in the hash object and copies the data values into the PDV. This raises two important points about the First and Last Methods:
- The First and Last Methods point to the logically first/last element of the associated hash object and copy their corresponding data values into the PDV.
- Both methods can be called regardless of the current position of the iterator pointer. Consequently, we can call the first/last method if the iterator does not yet point to any hash object element. But we can also call it if the iterator points to any element in the object.
data _null_; key=.; data=.; declare hash h(dataset:'have', ordered:'Y'); h.definekey('key'); h.definedata('key', 'data'); h.definedone(); declare hiter hi('h'); hi.first(); put key= // data=; hi.last(); put key= // data=; run;
Next and Prev Method
The Next and Prev Methods are usually used in conjunction with the First/Last Method to iterate through an entire hash object. You can see a typical example in the post from last week. In the code below, I declare the same hash object as above. I call the First Method() and then the Next() Method immediately after. This gives me the logically second element in the hash object copied into the PDV. Not surprisingly, when I do the same thing, but with the Last() and Prev() methods, I get the logically second last hash object element in the PDV. Three points worth noticing about the Next()/Prev() Methods:
- The Next/Prev copies the next/previous element into the PDV depending on the current position of the iterator pointer.
- Though I do not recommend it, the Next and Prev methods can be called when the iterator does not yet point to any element in the hash object. If you call the Next() Method while the iterator pointer dwells outside the hash object, the iterator will point to the logically first element in the hash object. The opposite goes for the Prev() method. I do not recommend this usage, since it can cause confusion about the current position of the iterator.
- Just like any other method, the Next/Prev methods return a zero code for success and non zero for failure. In this case, failure means that there are no next/previous elements to point to from the current position. This means that the failure call will place the iterator pointer outside the hash object.
data _null_; key=.; data=.; declare hash h(dataset:'have', ordered:'Y'); h.definekey('key'); h.definedata('key', 'data'); h.definedone(); declare hiter hi('h'); hi.first(); put key= / data= //; hi.next(); put key= / data= //; hi.last(); put key= / data= //; hi.prev(); put key= / data= //; run;
Small fun fact: The Next() Method is used internally to Check Whether Two Hash Objects Are Equal.
The four methods we have encountered above do not require any key value to function. This is in contrast to the Setcur Method(). The Setcur Method lets the SAS hash iterator point to the logically first element within a key group in the hash object. Let us look at a small example. In the code below, I create the same hash object as in the two preceding examples. Next, I call the Setcur Method assigned with key=2 as an argument and puts the results in the log. If you examine the log, you will see key=2 and data=3. Look at the data set at the top and verify that this is the first element in the key=2 group.
In the following Do While Loop, I iterate through the rest of the hash object from the current position. This is a quite unique feature of the iterator object in SAS. Unlike regular hash object methods such as Do_Over() and Find_Next(), the iterator object can cross key-boundaries. Conventional hash object methods can only iterate same-key groups.
data _null_; key=.; data=.; declare hash h(dataset:'have', ordered:'Y'); h.definekey('key', 'data'); h.definedone(); declare hiter hi('h'); rc=hi.setcur(key:2, key:30); put key= / data= //; do while (rc=0); put key= / data= //; rc=hi.next(); end; run;
In this post, I present the five available methods to the hash iterator object in SAS. These are the First, Last, Next, Prev and Setcur Methods. We have seen small, introductory examples of to use the methods and discussed how they differ from regular hash object methods. You can see an example of how to use several methods in the blog post Working with Consecutive Events in SAS.
If you want to learn more about the iterator object in SAS, consult the Documentation Page or the book Data Management Solutions Using SAS Hash Table Operations by Don Henderson and Paul Dorfman. Also, I use the iterator object in the post Print Content of a SAS Hash Object in the Log.
You can download the entire code from this post here.