How to append to a list in a for loop using ObjectScript
I want to append items to the list inside a for loop
Example:
set mylist = $ListBuild()
for i = 1:1:5 {
set item = "item"_i
set mylist = $ListBuild(mylist,item)
}
zw mylist
ObjectScriptObjectScript
The output should be:
mylist = $lb("item1", "item2", "item3", "itme4", "item5")
ObjectScriptObjectScript
The code snippet written above is not working, looking for correct way to do it.
Product version: IRIS 2024.3
Try the following:
set mylist = "" for i = 1:1:5 { set item = "item"_i set mylist = mylist _ $ListBuild(item) } zw mylist
$Listbuild lists have a separator that includes the length of the data in the next item of the list. This is why your original code wasn't working - $listbuild(mylist, item) would make a new list with two elements where the first item was the original list.
This is close - just want to start with mylist = "" otherwise you have an empty list item at the beginning
Hi Preedhi,
You could use $ListUpdate to update your list in the for loop as follows.
set mylist = $ListBuild() for i = 1:1:5 { set item = "item"_i set mylist = $ListUpdate(mylist,i,item) } zw mylist
This returns
USER>zw mylist mylist=$lb("item1","item2","item3","item4","item5")
Try concatenating the new item as follows:
set mylist = "" for i = 1:1:5 { set item = "item"_i set mylist = mylist_$ListBuild(item) }
The output is:
zw mylist mylist=$lb("item1","item2","item3","item4","item5")
2 options:
set mylist = "" for i = 1:1:5 { set item = "item"_i set mylist = mylist_$ListBuild(item) } zw mylist
kill mylist for i = 1:1:5 set $li(mylist,i)="item"_i zw mylist
Of the three options presented already, concatenating with $LISTBUILD() is by far the most performant. Running the following method
ClassMethod ListTest(l = 100000) { #; Concatenate with $LISTBUILD Set li="",zh=$ZHOROLOG For i=1:1:l Set li=li_$LISTBUILD(i) Write "Creating a list with length of ",$LISTLENGTH(li)," using $LISTBUILD() took ",$ZHOROLOG-zh," seconds",! #; Set $LIST Set li="",zh=$ZHOROLOG For i=1:1:l Set $LIST(li,i)=i Write "Creating a list with length of ",$LISTLENGTH(li)," using $LIST() took ",$ZHOROLOG-zh," seconds",! #; $LISTUPDATE Set li="",zh=$ZHOROLOG For i=1:1:l Set li=$LISTUPDATE(li,i,i) Write "Creating a list with length of ",$LISTLENGTH(li)," using $LISTUPDATE took ",$ZHOROLOG-zh," seconds" }
on a recent version of IRIS produces these results:
USER>d ##class(User.Test).ListTest() Creating a list with length of 100000 using $LISTBUILD() took .007244 seconds Creating a list with length of 100000 using $LIST() took 10.156168 seconds Creating a list with length of 100000 using $LISTUPDATE took 10.954107 seconds
...and it makes sense that using $listbuild to add at the end would be better than the other two options, which are general purpose ("find the position in the list and put something there").
Interestingly, for small examples, L<30, the first example is slower because it does both a $LISTBUILD plus a concatenation while the others just call a $LIST/$LISTUPDATE built-in. But for large examples, L>1000, the first example can win by at least one order of magnitude because the other examples include execution steps that take O(L**2) time.
An aside: when you have two $LIST values, L1 and L2 ,that you want to concatenate then you can just compute L1_L2 and string concatenation will do the job. Some programmers loop over L2 one element at at time and add that element to the end of L1. This can take n-squared time based on some product of the $LISTLENGTHs of L1 and L2. Using string concatenation just depends on the sum on the lengths of L1 and L2.
Another solution via $LISTFROMSTRING: