MATLAB has structure syntax like
a.b( index ).c = d ;
where index is an integer.
How do I create an IML list equivalent to the MATLAB statement? This will be a hierarchical heterogeneous list, I think.
Given the first instance, e.g.,
a.b(1).c = d ;
if index is incremented, how do I tell IML to create the second instance,
a.b(2).c = e;
so that an array of sublists is created?
Not sure what people are asking, but maybe study this program and see if it helps to answer your questions. At least it provides a concrete example that we can discuss.
proc iml;
package load ListUtil;
/* create list of lists.
Specify L$1$1, L$1$2, L$2$1, and L$2$2 */
L = ListCreate(3);
L$1 = ListCreate(2);
L$1$1 = 'L11';
L$1$2 = 12;
L$2 = ListCreate(2);
L$2$1 = 'L21';
L$2$2 = 22;
/* Now add a third item to L$2 and access it as L$2$3 */
newVal = 23;
L2 = ListGetSubItem(L, 2, 'm'); /* get the sublist you want to expand */
call ListAddItem(L2, newVal); /* expand it */
call ListSetSubItem(L, 2, L2, 'm'); /* set it back into the list */
call struct(L);
check = L$2$3; /* make sure the new item exists */
print check;
Please post a SAS/IML program that shows what you are trying to accomplish. Use the IML syntax, not the syntax from a different language.
As a general rule, use ListAddItem to add a new item to an existing list. If the item you add is a list, you can use ListAddItem to add items to that list, thus emulating a hierarchical structure.
Hi Rick,
Can you give an example of how you can use ListAddItem to extend a sublist? I can make it work at the top level, but not lower down in the hierarchy.
Please show what you have tried.
Keep in mind that MATLAB data structures are more general than lists. The main purpose of the SAS/IML lists is to pack objects of various types into a single object that can be passed to and from modules. You might be able to coerce lists to emulate other data structures, but you will have to be clever.
Here is an example. If I create a list with 3 items where the second item is itself a list - like this:
L = [[1:3], [i(2),i(3)], [4:6]];
Then I might want to add i(4) to the sublist. I have tried syntax like:
Call ListAddItem(L$2, i(4));
but this, and using L[2] instead of L$2, both leave L unmodified. If by being clever you mean something like:
L$2 = [ L$2 || [i(4)] ];
then this works but essentially I have just manually reconstructed L$2. It feels like there should be a subroutine called ListAddSubItem to do what I want, but it is not there.
I thank all of you for your interest in my question and for your suggestions.
I am trying to create a SAS/IML list with the following structure:
a$1$c = 'item 1'
a$2$c = 'item 2'
a$3$c = 'item 3'
b$1$c = 'item 1'
b$2$c = 'item 2'
b$3$c = 'item 3'
b$4$c = 'item 4'
...
After studying Dr. Wicklin's example, I think that this code does the task:
-----------
proc iml ; package load listutil ;
L = [] ;
do i = 1 to 2 ;
call ListAddItem( L, [ #type='input', i, #item='item' + char(i) ] ) ;
end ;
do i = 1 to 3 ;
call ListAddItem( L, [ #type='output', i, #item='item' + char(i) ] ) ;
end ;
call struct( L ) ;
quit ;
----------
How can I produce the same result using the list syntax "$" instead of "ListAddItem" ?
Ross
Not sure what people are asking, but maybe study this program and see if it helps to answer your questions. At least it provides a concrete example that we can discuss.
proc iml;
package load ListUtil;
/* create list of lists.
Specify L$1$1, L$1$2, L$2$1, and L$2$2 */
L = ListCreate(3);
L$1 = ListCreate(2);
L$1$1 = 'L11';
L$1$2 = 12;
L$2 = ListCreate(2);
L$2$1 = 'L21';
L$2$2 = 22;
/* Now add a third item to L$2 and access it as L$2$3 */
newVal = 23;
L2 = ListGetSubItem(L, 2, 'm'); /* get the sublist you want to expand */
call ListAddItem(L2, newVal); /* expand it */
call ListSetSubItem(L, 2, L2, 'm'); /* set it back into the list */
call struct(L);
check = L$2$3; /* make sure the new item exists */
print check;
Thank you Rick, I see how to do it now. So following your example I could make my own version of ListAddSubItem as follows:
proc iml;
start ListAddSubItem(A, Pos, Val);
if type(A) ^= 'L' then return;
B = ListGetSubItem(A, Pos, 'm');
if type(B) = 'L' then call ListAddItem(B, Val);
call ListSetSubItem(A, Pos, B, 'm');
finish;
package load listutil;
L = [ 2, [5, 6], 9 ];
call ListAddSubItem(L, 2, 7);
call struct(L);
quit;
> How can I produce the same result using the list syntax "$" instead of "ListAddItem" ?
You can't, unless you use concatenation as Ian showed earlier. The '$' syntax refers to an item that already exists. The ListAddItem function creates a new item in the list.
Think of the $ operator as analogous to subscripts for matrices. If you define
m = 11:13;
you cannot reference m[4] because that element does not exist. If you want to add a new item to the m matrix, you need to use concatenation or "allocate and copy":
m1 = m || {14};
or
m2 = j(1, ncol(m)+1, .);
m2[1:3] = m;
m2[4] = 14;
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.