【问题标题】:How to parse two characters at a time for one Iteration?如何一次解析两个字符进行一次迭代?
【发布时间】:2019-06-14 22:27:04
【问题描述】:

我有一个匹配 2 个字符并解析数据的书面查询,但我觉得我这样做的方式是错误的。让我和你分享我的逻辑

DEFINE VARIABLE I                   AS INTEGER   NO-UNDO.
DEFINE VARIABLE cData               AS CHARACTER NO-UNDO.
DEFINE VARIABLE cParsData           AS CHARACTER NO-UNDO.

ASSIGN
       cData = 'PRRSCLPP0123456789'.

DO I = 1 TO LENGTH(cData):

   cParsData = SUBSTRING(cData,I).
   IF cParsData MATCHES 'PP*' THEN MESSAGE SUBSTRING(cParsData,4,9).

END.

正如您所见,我的做法是错误的,我认为它每次迭代都会解析每个字符,但我需要的是它应该每次迭代解析两个字符,以便我们可以匹配“PP”。您可以共享或更改不同方式的逻辑以获得相同的输出

【问题讨论】:

    标签: openedge progress-4gl


    【解决方案1】:

    很难想象为什么要一次遍历一个字符来查找“PP”,然后吐出字符 4 到 13。这样做会简单得多:

    define variable myData  as character no-undo.
    define variable foundIt as integer   no-undo.
    
    myData = "PRRSCLPP0123456789".
    
    foundIt = index( myData, "PP" ).
    if foundIt > 0 then 
      message substring( myData, 4, 9 ).
    

    如果有理由一次遍历该字符串一个字符,我认为它不能包含在您的代码示例或问题中。

    附带说明: MATCHES "PP*" 等价于 BEGINS "PP"。在这种情况下,这并不重要,但在字符串比较时不必要地抛出 MATCHES 是一个坏习惯。特别是如果该习惯最终出现在 WHERE 子句中。在 WHERE 子句中使用 MATCHES 将导致表扫描。这几乎总是一个坏主意。

    如果您尝试在找到“PP”的位置之后输出 N 个字符(而不是硬编码的 4 到 13),您可以这样做(假设 n = 9):

    define variable myData  as character no-undo.
    define variable foundIt as integer   no-undo.
    
    myData = "PRRSCLPP0123456789".
    
    foundIt = index( myData, "PP" ).
    if foundIt > 0 then 
      message substring( myData, foundIt + 1, 9 ).
    

    【讨论】:

    • 这显然是一种优于迭代挖掘的解决方案。不过,我仍然很难理解正在解决的实际问题。
    • 我也对此感到困惑。如果确实需要,则此页面上(当前)不存在原因。我能想到的唯一解释是,作为一个使用 Progress 编程的新手,他没有接触过像 INDEX() 这样的函数,因此决定一次将字符串分开一个字符。在过去的美好时光中,我们可以弹出“袖珍进度”并轻松找到合适的功能。在勇敢的新无纸世界中,仅仅浏览可能的嫌疑人并不容易;)
    • 是的。缺少命名空间和/或结构化文档(这里都是关于字符串,这里是数字等)。也很难知道有什么可用。
    【解决方案2】:

    我不太明白你想做什么。您要搜索字符串并查看其中是否有“PP”吗?然后,您不需要在迭代中执行此操作。简单的

    cData MATCHES "*PP*" 会告诉你的。

    如果“PP”是某种分隔符,并且您想对前后的数据做一些事情,则可以:

    DEFINE VARIABLE I                   AS INTEGER   NO-UNDO.
    DEFINE VARIABLE cData               AS CHARACTER NO-UNDO .
    DEFINE VARIABLE cParsData           AS CHARACTER NO-UNDO.
    
    ASSIGN
       cData = 'PRRSCLPP0123456789'.
    
    DO I = 1 TO LENGTH(cData):
    
        cParsData = SUBSTRING(cData,I, 2).
        IF cParsData = 'PP' THEN DO:
            DISPLAY 
                SUBSTRING(cData, i + 2)    FORMAT "x(20)" LABEL "After PP" 
                SUBSTRING(cData, 1, i - 1) FORMAT "x(20)" LABEL "Before PP".
        END.
    
    END.
    

    这仅适用于字符串中出现一次“PP”。您应该尝试更好地解释您所追求的目标。

    您在另一个答案的评论中留下了更多信息:

    如果 PP 真的总是在位置 10(和 11)或 20(和 21)并且您只想要以下 10 个字符,那么您可以这样做:

    DEFINE VARIABLE cData1 AS CHARACTER NO-UNDO.
    DEFINE VARIABLE cData2 AS CHARACTER NO-UNDO.
    /* Position 10 and 11 */
    cData1 = 'PRRSCLAAAPP0123456789'.
    /* Position 20 and 21 */
    cData2 = 'PRRSCLAAAPRRSCLAAAPP9876543210AA'.
    
    FUNCTION parse  RETURNS CHARACTER 
        (INPUT cString AS CHARACTER ):
        IF INDEX(cString, "PP") > 0 THEN 
            RETURN SUBSTRING(cString, INDEX(cString, "PP") + 2, 10 ).
        ELSE 
            RETURN "".
    
    END.
    
     MESSAGE cData1 " ->" parse(cData1) SKIP
             cData2 " ->" parse(cData2) VIEW-AS ALERT-BOX.
    

    【讨论】:

    • 谢谢人。我们不将 DO 循环称为迭代也是有效的吗?正如您所知,每次“I”的值都会根据 cData 的长度而变化。所以我认为我们可以调用这个迭代,这就是我提到的原因。如果我错了,请纠正我
    • cParsData = SUBSTRING(cData,I, 2) 每次迭代查看 2 个字节, i 增加所以第一次迭代它查看位置 1 和 2,第二次迭代 2 和 3 等。如果这是你需要做的,不仅仅是看到 PP 在字符串中,您需要某种迭代是的。
    • 更新了我的答案,以反映在另一个答案的评论中提到的固定位置。
    • 嗨 Jensd,谢谢你,这就是我要找的东西.. 抱歉我的知识不好,因为我还年轻,还处于开始逐步学习一切的阶段
    猜你喜欢
    • 2020-03-20
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 2012-08-10
    • 2019-08-24
    • 1970-01-01
    相关资源
    最近更新 更多