字符串替换



在您看来,在不使用$R的情况下替换字符串中的某些内容的最佳方法是什么?我已经写了一个global,我正试图用PAUL代替PETER,但不使用$R。以下是我认为可行的迭代,但它只是取代了第一个PETER。对于同一条线上的多个Peters,你们有什么建议?

Start  
SET ary="^XA"
SET queryary=$QUERY(@ary@(""))
WRITE !,@queryary
FOR   {
SET queryary=$QUERY(@queryary) 
    QUIT:queryary=""  
    w !,$p(@queryary,"PETER",1)_"PAUL"_$p(@queryary,"PETER",2,$l(@queryary,"PETER"))  
}
  QUIT

这是我的第二次尝试,但我仍然需要多次运行它才能执行所有更改。我的环路里少了什么东西吗?

  Start  
  N ary
  S ary="^XA"
  S queryary=$Q(@ary@(""))
  S FROM="PETER"
  S TO="PAUL"
  W !,@queryary
  F   S queryary=$Q(@queryary) Q:queryary=""  w !,@queryary   d 
  . f  s $E(@queryary,$F(@queryary,FROM)-$L(FROM),$F(@queryary,FROM))=TO_" "     Q:ary'["PETER"  
  QUIT

不使用$replace是很棘手的。我使用了$find和$extract函数。。。我用"BACH"取代"MOZART"

mozartdocument
s ^XA(1)="ONCE UPON A TIME A COMPOSER NAMED MOZART WROTE"
s ^XA(2)="THE 'MOZART PIANO CONCERTO NUMBER ONE'. MOZART"
s ^XA(3)="MOZART 12 MOZART HANDEL MOZART MOZART 12"
s ^XA(4)="MAN MOZART MUMPS MANY MUNCHKINS MOZART"
s ^XA(5)="MOVE ALONG, NOTHING TO SEE HERE!"
s ^XA(6)="123 MOZART 456"
s ^XA(7)="HAPPILY EVER AFTER!"
for z = 1:1:7 {
    do {
        set x = $find(^XA(z),"MOZART")
        set $extract(^XA(z),x-6,x-1)="BACH"
    } while x > 0
    write !,^XA(z)
} write !

如果你在Cache中工作,并且想要一个实用程序,%GCHANGE是一个非常强大的程序,只用于执行你所描述的操作。我一直把它作为一个实用程序使用,从来没有从程序中调用过它,但我相信在调用和传递参数的地方会有标签。

另一件事是,您在循环中使用多个间接寻址,这将降低程序的速度。我建议将所有这些组合成一个字符串,并使用E(X)ecute命令对整个字符串进行间接寻址。您可以看到下面提供的示例。

我包括了两种不同的替换字符串的方法。一种方法使用$P和$L,类似于Evgeny Shvarov的建议,第二种方法使用$F和$E。

第二种方法在100000个节点的全局上平均执行速度快33%,每个节点有4个替换。

我将包括我编写的数据生成器和测试函数。我在遗留的MUMPS代码中编写了这些代码,所以它可以跨平台工作。

更新:我刚刚查看了GTM文档。%GCE是一个类似的实用程序,可在GTM中使用。更新:我更改了REPLACE函数,以正确解释C4xuxo描述的LISA-to-ELISA问题。它仍然比使用$P$L执行得更快。

更新:在REPLACE函数中对PS的值进行了调整,以修复一个错误;

;GLOBAL REPLACE METHOD 
GLBREPLACE(GLB,STR1,STR2) ;(GLOBAL NAME, STRING TO MATCH, STRING TO REPLACE WITH)
 S CMD="N I S I="""" F  S I=$O("_GLB_"(I)) Q:I=""""  S "_GLB_"(I)=$$REPLACE("_GLB_"(I),"""_STR1_""","""_STR2_""")"
 X CMD Q
;STRING REPLACE METHOD
REPLACE(STR,V1,V2) ;(INPUT STRING, STRING TO MATCH, STRING TO REPLACE WITH)
 N I,L,F1,F2,PS S PS=0,L=$L(STR,V1) F I=1:1:L-1 S F2=$F(STR,V1,PS),F1=F2-$L(V1),$E(STR,F1,F2-1)=V2,PS=F2+$L(V2) 
 Q STR

;======================================================================
;ADDITINAL FUNCTIONS
;THIS IS AN ALTERNATE METHOD, DOESN'T ADDRESS THE LISA TO ELISA PROBLEM
REPLACE2(STR,V1,V2) 
 N I F I=1:1:$L(STR,V1)-1 S STR=$P(STR,V1)_V2_$P(STR,V1,2,$L(STR,V1))
 Q STR
TESTGLBREPLACE ;THIS FUNCTION TESTS GLBREPLACE AND MEASURS PERFORMANCE
 S STIM=$ZTS S COUNT=100000
 D GENDATA(COUNT),GLBREPLACE("^XA","Peter","PAUL")
 S ETIM=$ZTS,TIMDIF=$P(ETIM,",",2)-$P(STIM,",",2),OCCURS=COUNT*4
 W !,"REPLACED "_OCCURS_" OCCURRENCES IN "_TIMDIF_" SECONDS"
 Q
GENDATA(L) ;THIS FUNCTION GENERATES DATA FOR A GIVE COUNT(L=INTEGER)
 F I=1:1:L S ^XA(I)="Peter Piper picked a peck of pickled peppers; A peck of pickled peppers Peter Piper picked; If Peter Piper picked a peck of pickled peppers, Where's the peck of pickled peppers Peter Piper picked"
 Q

这个怎么样?

    ClassMethod PeterPaul()
{
    s ^XNAME(1)="PETER PIPER PICKED A PEPPER"
    s ^XNAME(2)="PETER ENJOYS PIZZA'. PETER" 
    s ^XNAME(3)="PETER WAS BORN IN 1982" 
    s ^XNAME(4)="PETER LIKES PIZZA AND FRENCH FRIES'. PETER" 
    s ^XNAME(5)="THE PETER WROTE A BOOK CALLED PETER ADVENTURES." 
    s ^XNAME(6)="THE PETER HAD THREE KIDS.' PETER JR AND PETER III"
    s ^XNAME(7)="PETER MARRIED MARY."
    s i=$O(^XNAME(""))
    while i'="" {
        s ^XNAME(i)=..Replace(^XNAME(i),"PETER","PAUL")
        s i=$O(^XNAME(i))
        }
    q
}
ClassMethod Replace(str, from, to As %String)
{
        while $F(str,from) {
            s str=$P(str,from)_to_$P(str,from,2,$L(str,from))
            }
        quit str
}

不幸的是,我还不能发表评论,这应该更像是对以前的解决方案的评论,以及关于Cache生成的实际腮腺炎是什么的问题。所以,如果有人回复并确认我的可疑之处,那就太好了,因为我认为之前的解决方案中有一个bug。

因此,假设Cache编译以下解决方案:

ClassMethod Replace(str, from, to As %String)
{
        while $F(str,from) {
            s str=$P(str,from)_to_$P(str,from,2,$L(str,from))
            }
        quit str
}

类似的东西:

REPLACE(str,from,to)
        ;
        F I=1:1 Q:'$F(str,from)  D
        .       S str=$P(str,from)_to_$P(str,from,2,$L(str,from))
        Q str

当我的实际from变量包含在to,中时,此代码中有一个严重的错误,将导致无限循环

例如,将"LISA"更改为"ELISA"、"ELISABETH"、"ALISA"、"MELISA"。

下面使用的示例将DAN更改为DANIEL。

在GTM上测试(循环在10次迭代后手动中断,否则将是无限的):

GTM>W $$REPLACE^ZZTEST("DAN SMITH","DAN","DANIEL")
DANIELIELIELIELIELIELIELIELIELIEL SMITH

考虑到这一点,我建议这样做:

REPLACE2(str,from,to)
        ;
        N str2
        S str2=""
        F I=1:1:$L(str,from)-1 D
        .       S str2=str2_$P(str,from)_to
        .       S str=$P(str,from,2,$L(str,from))
        ;add the last piece if it exists or in case nothing to replace add all.
        Q str2_str

在GTM:中测试

GTM>W $$REPLACE2^ZZTEST("DAN SMITH","DAN","DANIEL")
DANIEL SMITH
GTM>W $$REPLACE2^ZZTEST("DAN SMITH DAN","DAN","DANIEL")
DANIEL SMITH DANIEL
GTM>W $$REPLACE2^ZZTEST("DAN SMITH DAN DAN DAN","DAN","DANIEL")
DANIEL SMITH DANIEL DANIEL DANIEL
GTM>W $$REPLACE2^ZZTEST("DAN SMITH DAN DAN DAN","DANA","DANIEL")
DAN SMITH DAN DAN DAN

当然,这不会是最终的解决方案,因为它仍然包含错误,例如生成了名称LISABETH。。。。

GTM>W $$REPLACE2^ZZTEST("ELISABETH SMITH","ELISA","LISA")
LISABETH SMITH
GTM>W $$REPLACE2^ZZTEST("ELISA ELISABETH SMITH ELISA","ELISA","LISA")
LISA LISABETH SMITH LISA
GTM>W $$REPLACE2^ZZTEST("ELISA ELISABETH SMITH ELISA"," ELISA","LISA")
ELISALISABETH SMITHLISA
GTM>W $$REPLACE2^ZZTEST("ELISA ELISABETH SMITH ELISA"," ELISA ","LISA")
ELISA ELISABETH SMITH ELISA
GTM>W $$REPLACE2^ZZTEST("ELISA ELISABETH SMITH ELISA"," ELISA","LISA")
ELISALISABETH SMITHLISA
GTM>W $$REPLACE2^ZZTEST("ELISA ELISABETH SMITH ELISA","ELISA ","LISA")
LISAELISABETH SMITH ELISA

为了绕过这个问题,需要添加额外的逻辑,以理解如果名称在开头,则如果名称在结尾,则需要为"name",否则在中间为"name"。

类似(可能可以优化):

REPLACE2(str,from,to)
        ;
        N from2,str2
        S str2=""
        S from2=" "_from_" "
        ; check if string begins with name
        I $E(str,1,$L(from))_" "=(from_" ") S str2=to,str=$E(str,$L(from)+1,$L(str))
        ; search for name with spaces
        F I=1:1:$L(str,from2)-1 D
        .       S str2=str2_$P(str,from2)_" "_to
        .       S str=" "_$P(str,from2,2,$L(str,from2))
        ; check if finishes with name
        I $L(str)>=$L(from) D
        .       I $E(str,$L(str)-$L(from),$L(str))=(" "_from) S str2=str2_$E(str,1,$L(str)-$L(from))_to,str=""
        .
        Q str2_str      ;add the last piece if it exists

GTM:测试

GTM>W $$REPLACE2^ZZTEST("MELISA ELISA ELISABETH ALISA ELISA","ELISA","LISA")
MELISA LISA ELISABETH ALISA LISA
GTM>W $$REPLACE2^ZZTEST("MELISA ELISA ELISABETH ALISA ELISA","LISA","ELISA")
MELISA ELISA ELISABETH ALISA ELISA
GTM>W $$REPLACE2^ZZTEST("LISA MELISA ELISA ELISABETH LISA  ALISA LISA","LISA","ELISA)
ELISA MELISA ELISA ELISABETH ELISA  ALISA ELISA
GTM>W $$REPLACE2^ZZTEST("LISA MELISA ELISA ELISABETH LISA ALISA LISA","LISA","ELISA)
ELISA MELISA ELISA ELISABETH ELISA ALISA ELISA

但如果你决定或收到以下输入,仍然可能无法满足你的所有需求:

GTM>W $$REPLACE2^ZZTEST("ELISA,SMITH","ELISA","LISA")
ELISA,SMITH

腮腺炎发展委员会会议记录中引用的标准REPLACE是$$REPLACE^XLFSTR()。我经常把它用作printf模拟器。

替换(IN,SPEC);请参阅MDC分钟中的$$REPLACE。Q: "$D(IN)"Q:$D(SPEC)'>9在N%1、%2、%3、%4、%5、%6、%7、%8中S%1=$L(IN),%7=$J(",%1),%3=",%6=99999 F S%3=$O(规范(%3))Q:%3="S%6(%6)=%3,%6=%6-1F%6=0:0 S%6=$O(%6(%6))Q:%6'>0 S%3=%6(%6)D:$D(规范(%3))#2 RE1S%8="F%2=1:1:%1 D RE3Q%8;RE1 S%4=$L(%3),%5=0 F S%5=$F(IN,%3,%5)Q:%5

以下是关于如何使用它的参考:

http://hardhats.org/kernel/html/x-replace%5Exlfstr.shtml.

相关内容

  • 没有找到相关文章

最新更新