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?
Comments
I don't know the fastest way. I know a way:
set list = $lb("stri,ng", $c(0), 2)
set list2 = "", ptr = 0
while $listnext(list, ptr, elem) {
if elem'=$C(0) {
set list2 = list2 _ $LB(elem)
} else {
set list2 = list2 _ $LB()
}
}
Thanks, Robert.
It works fast, but replaces $c(0) with empty string instead of empty element.
Can $list replace replace $c(0) with empty element?
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 ! }Works fast too.
Unless you have list with $c(3,1,0) as element
USER>set list = $lb("stri,ng", $c(0), 2, $c(3,1,0), 3)
USER>set list = $replace(list, $lb($c(0)), $lb())
USER>zw list
list=$c(9,1)_"stri,ng"_$c(1,3,4,2,5,1,1,3,4,3)
USER>w $LL(list)
W $LL(list)
^
<LIST>
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>I think best way is to use $li to replace the item.
Then you need to set "list" again.
There's documentation on thia.
Can you please elaborate?
Elaborated ;) Full classmethod Main() now.
You can get rid of two lines:
set ways = $lb("listnext", "listfind", "lfs", "base")and
set way = $lg(ways, i)
if you change for to:
for way="listnext", "listfind", "lfs", "base" {![]()
![]()
![]()
,p=0
for set p=$LISTFIND(list,$C(0),p) quit:'p set $LIST(list,p)=""
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.
Do not forget that $lb is just a list, concatenated list of single $lb, and $lb is a string in binary format.. So, just $replace, will work
USER>set list = $lb("stri,ng", $c(0), 2)
USER>set list = $replace(list, $lb($c(0)), $lb())
USER>zw list
list=$lb("stri,ng",,2)