Announcement

Collapse
No announcement yet.

replace a part of a delimited string

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replace a part of a delimited string

    It works, so now let's make it better.

    Code:
    #COMPILE EXE
    #DIM ALL
    
    FUNCTION ParsRepl (OrigString AS STRING, Delim AS STRING, FldNum AS LONG, ReplString AS STRING) AS STRING
    LOCAL Pieces() AS STRING
    
        DIM Pieces(1 TO PARSECOUNT(OrigString,Delim)) AS STRING
        PARSE OrigString, Pieces(), Delim
        Pieces(FldNum) = ReplString
        FUNCTION = JOIN$(Pieces(),Delim)
    
    END FUNCTION
    
    FUNCTION PBMAIN () AS LONG
    LOCAL TSV AS STRING
    
        TSV = BUILD$("Mary",$TAB,"had",$TAB,"a",$TAB,"little",$TAB,"lamb")
        PRINT TSV
        TSV = ParsRepl(TSV,$TAB,4,"young")
        PRINT TSV
        WAITKEY$
    
    END FUNCTION
    The real world application will be calling ParsRepl tens of thousands of times, so how can I make it better? It is important all other fields be left unchanged.
    Erich Schulman (KT4VOL/KTN4CA)
    Go Big Orange

  • #2
    Erich,
    not fully tested but this is faster:
    Code:
    FUNCTION ParsRepl2 (OrigString AS STRING, Delim AS STRING, FldNum AS LONG, ReplString AS STRING) AS STRING
    LOCAL r,n AS LONG
    
    FOR r&=1 TO FldNum -1              'scan the string forwards to the required delim
        n=INSTR(n+1,OrigString,Delim)
    
    NEXT
    
    FUNCTION = LEFT$(OrigString,n)+ReplString+Delim+RIGHT$(OrigString,-INSTR(n+1,OrigString,Delim))
               
    END FUNCTION
    Paul.

    Comment


    • #3
      From looking at the code, I don't think it will work with my real world data because two fields are too likely to contain the same data.

      Here is a real row, albeit edited for privacy.
      Code:
      8194	DORA	EXPLORER	11/07/02	06/19/89	00/00/00	23.25	.00	.00	.00	.00	.00	01/04/08	2267C	143.16	68	29.82	123-45-6789
      As you can see, several columns (7-12) contain ".00", and that is typical. But each of those columns can contain any value .00 through 99.99.

      It is very important only the correct column be updated. We don't want the IRS to have Swiper the Fox pay us a visit ("You'll never find your money now!").
      Erich Schulman (KT4VOL/KTN4CA)
      Go Big Orange

      Comment


      • #4
        Erich,
        eh? My code scans forward to the one field you specify by FldNum and replaces it. Other fields should be unaffected.

        Paul.

        Comment


        • #5
          I was looking visually, but I am seeing better how it works now. I have plenty of rows I can test it on.
          Erich Schulman (KT4VOL/KTN4CA)
          Go Big Orange

          Comment


          • #6
            As long as the delimiter character is not included in any of the column data (like commas in quote encapsulated data for CSV files for example), Paul's code looks like it would work fine.
            Bernard Ertl
            InterPlan Systems

            Comment


            • #7
              I see Paul did basically this above already, but hey, this includes a little test code.

              Code:
              #COMPILE EXE
              #DIM ALL
              
              FUNCTION ParsRepl (OrigString AS STRING, Delim AS STRING, FldNum AS LONG, ReplString AS STRING) AS STRING
              LOCAL Pieces() AS STRING
              
                  DIM Pieces(1 TO PARSECOUNT(OrigString,Delim)) AS STRING
                  PARSE OrigString, Pieces(), Delim
                  Pieces(FldNum) = ReplString
                  FUNCTION = JOIN$(Pieces(),Delim)
              
              END FUNCTION
              
              FUNCTION ParsReplFast (OrigString AS STRING, Delim AS STRING, FldNum AS LONG, ReplString AS STRING) AS STRING
              LOCAL cnt, cnt2, ii AS LONG
              
                  FOR ii = 1 TO fldNum - 1
                     cnt = INSTR(cnt + 1, origString, delim)
                  NEXT
                  cnt2 = INSTR(cnt + 1, origString, delim)
                  FUNCTION = LEFT$(origString, cnt) & replString & MID$(origString, cnt2)
              
              END FUNCTION
              
              FUNCTION PBMAIN () AS LONG
              LOCAL TSV AS STRING, ii AS LONG, t, t2 AS QUAD
              
                  TSV = BUILD$("Mary",$TAB,"had",$TAB,"a",$TAB,"little",$TAB,"lamb")
                  TSV = BUILD$(TSV,TSV,TSV,TSV,TSV,TSV,TSV)
              '    PRINT TSV
                  TIX t
                  FOR ii = 1 TO 10000
                     TSV = ParsRepl(TSV,$TAB,20,"young")
                  NEXT
                  TIX END t
              
                  PRINT TSV, t
                  PRINT
                  TSV = BUILD$("Mary",$TAB,"had",$TAB,"a",$TAB,"little",$TAB,"lamb")
                  TSV = BUILD$(TSV,TSV,TSV,TSV,TSV,TSV,TSV)
              '    PRINT TSV
                  TIX t2
                  FOR ii = 1 TO 10000
                     TSV = ParsReplFast(TSV,$TAB,20,"young")
                  NEXT
                  TIX END t2
              
                  PRINT TSV, t2
                  PRINT
                  PRINT "so ParsReplFast was "; STR$(t / t2, 4); " times faster."
                  WAITKEY$
              
              END FUNCTION
              Last edited by John Gleason; 6 Feb 2009, 08:18 PM. Reason: red 2

              Comment


              • #8
                Originally posted by Paul Dixon View Post
                Erich,
                not fully tested but this is faster:
                Code:
                FUNCTION ParsRepl2 (OrigString AS STRING, Delim AS STRING, FldNum AS LONG, ReplString AS STRING) AS STRING
                LOCAL r,n AS LONG
                
                FOR r&=1 TO FldNum -1              'scan the string forwards to the required delim
                    n=INSTR(n+1,OrigString,Delim)
                NEXT
                
                FUNCTION = LEFT$(OrigString,n)+ReplString+Delim+RIGHT$(OrigString,-INSTR(n+1,OrigString,Delim))
                           
                END FUNCTION
                Paul.
                Nice example Paul - thanks! I'll use your code in some of my stuff for sure.
                Paul Squires
                FireFly Visual Designer (for PowerBASIC Windows 10+)
                Version 3 now available.
                http://www.planetsquires.com

                Comment


                • #9
                  I use a similar function. However you might want to add a little error checking in the code in case someone sends something unexpected. For example if they want to replace the 9th field in a string that only has 4 delimiters in it. In that case it should return the original string since their is nothing to replace. (unless you want it to add the extra delimiters needed first.) It will add a little time to the function, but not much.

                  For example this would catch that issue:
                  Code:
                  FUNCTION ParsRepl2 (OrigString AS STRING, Delim AS STRING, FldNum AS LONG, ReplString AS STRING) AS STRING
                     LOCAL r,n AS LONG
                  
                     if ParseCount(OrigString, Delim) => FldNum then
                  
                        FOR r=1 TO FldNum -1              'scan the string forwards to the required delim
                           n=INSTR(n+1,OrigString,Delim)
                        next r
                        FUNCTION = LEFT$(OrigString,n)+ReplString+Delim+RIGHT$(OrigString,-INSTR(n+1,OrigString,Delim))
                  
                     else
                        function = OrigString   'original string did not have enough delimiters so return original string
                     end if
                  END FUNCTION
                  "I haven't lost my mind... its backed up on tape... I think??" :D

                  Comment


                  • #10
                    ParseReplace function:

                    http://www.powerbasic.com/support/pb...ad.php?t=23192
                    kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                    Comment

                    Working...
                    X