Question
· Aug 28, 2018

Replace elements in $lb

Let's say I have a list structure:

set list = $lb("stri,ng", $c(0), 2)

I want to replace all $c(0) elements with empty elements, so my list would look like:

set list = $lb("stri,ng", , 2)

What's the fastest way to do that?

Discussion (13)1
Log in or sign up to continue

Ed, it's not about speed, but about syntax sugar on "for cycles". you can go like that: 

 
/// do ##class(POI.Test).main() 
ClassMethod main(rounds As %Integer = 1000, size As %Integer = 10, nullPercent As %Integer = 20) {
 set list = ..getList(size, nullPercent) 
 write !,"Rounds: ", rounds 
 write !,"Size: ", size 
 write !,"NullPercent: ", nullPercent 
 write !,"List: " 
 zwrite list
for way="listnext", "listfind", "lfs", "base" {

  set start = $zh set list2 = $classmethod(,way, rounds, list)

  set end = $zh set time = end - start 
 write !,"Way: ", way 
 write !,"Time: ", time 
write !,"List: "
 zwrite list2

  write ! }

Here's a somewhat contrived case where that technique fails:

USER>s weirdlist=$lb("Very "_$lb($c(0))_" odd data",$c(0),2)
 
USER>s replaced=$replace(weirdlist,$lb($c(0)),$lb())
 
USER>zw weirdlist
weirdlist=$lb("Very "_$c(3,1,0)_" odd data",$c(0),2)
 
USER>zw replaced
replaced=$c(19,1)_"Very "_$c(1)_" odd data"_$c(1,3,4,2)
 
USER>

Speed comparison:

Class POI.Test
{

/// do ##class(POI.Test).main()
ClassMethod main(rounds As %Integer = 1000, size As %Integer = 10, nullPercent As %Integer = 20)
{
    set list = ..getList(size, nullPercent)
    
    write !,"Rounds: ", rounds
    write !,"Size: ", size
    write !,"NullPercent: ", nullPercent
    write !,"List: "
    zwrite list
        
    set ways = $lb("listnext", "listfind", "lfs", "base")
    for i=1:1:$ll(ways) {
        set way = $lg(ways, i)
        set start = $zh
        
        set list2 = $classmethod(,way, rounds, list)
        
        set end = $zh
        
        set time = end - start
        
        write !,"Way: ", way
        write !,"Time: ", time
        write !,"List: "
        zwrite list2
        write !
    }
}

ClassMethod base(rounds As %Integer = 1000, list As %List) As %List
{
    for i=1:1:rounds {
        set origList = list
    }
    quit origList
}

ClassMethod listfind(rounds As %Integer = 1000, list As %List)
{
    for i=1:1:rounds {
        set origList = list
        set ptr=0
        for  set ptr=$LISTFIND(origList, $c(0), ptr) quit:'ptr  set $LIST(origList, ptr, ptr)=$lb()
    }
    quit origList
}

ClassMethod listnext(rounds As %Integer = 1000, list As %List)
{
    for i=1:1:rounds {
        set list2 = ""
        set ptr = 0
        while $listnext(list, ptr, elem) {
            if elem'=$C(0) {
                set list2 = list2 _ $LB(elem)
            } else {
                set list2 = list2 _ $LB()
            }
        }
    }
    quit list2
}

ClassMethod lfs(rounds As %Integer = 1000, list As %List)
{
    for i=1:1:rounds {
        set str = $lts(list)
        set str = $tr(str, $c(0))
        set list2 = $lfs(str)    
    }
    quit list2
}

ClassMethod getList(size As %Integer = 10, nullPercent As %Integer = 20) As %List
{
    set list = ""
    for i=1:1:size {
        set list = list _ $lb($select($random(101)<=nullPercent:$c(0),1:$random(50)))
    }
    quit list
}

Results:

POI>do ##class(POI.Test).main(1000000)
 
Rounds: 1000000
Size: 10
NullPercent: 20
List: list=$lb(25,20,$c(0),$c(0),4,42,$c(0),28,44,3)
 
Way: listnext
Time: .944814
List: list2=$lb(25,20,,,4,42,,28,44,3)
 
 
Way: listfind
Time: .610244
List: list2=$lb(25,20,,,4,42,,28,44,3)
 
 
Way: lfs
Time: .430088
List: list2=$lb("25","20","","","4","42","","28","44","3")
 
 
Way: base
Time: .032151
List: list2=$lb(25,20,$c(0),$c(0),4,42,$c(0),28,44,3)

listfind solution seems optimal.