How to get the word_before and word_after a specific keyword from a string.

Just starting out? Need help? Post your questions and find answers here.
User avatar
idle
Always Here
Always Here
Posts: 5840
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: How to get the word_before and word_after a specific keyword from a string.

Post by idle »

Oso wrote: Sat Aug 27, 2022 10:03 pm
idle wrote: Sat Aug 27, 2022 2:27 am @Oso you've just taken 2 steps back, each post was an improvement over the others, my post also simplified and improved the runtime complexity of Infratec's last code, he's a PB guru, he knows his stuff.
I've got ya, my apologies for 'throwing the spanner in the works', as they say :cry:
sorry I didn't mean to sound harsh. Olli had your back and gave me a good kicking!
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: How to get the word_before and word_after a specific keyword from a string.

Post by Oso »

idle wrote: Sat Aug 27, 2022 10:45 pm
Oso wrote: Sat Aug 27, 2022 10:03 pm I've got ya, my apologies for 'throwing the spanner in the works', as they say :cry:
sorry I didn't mean to sound harsh. Olli had your back and gave me a good kicking!
No worries, I was slow to grasp the objective. :D
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post by Mijikai »

Could not miss the party 8)

Code:

Code: Select all

EnableExplicit

Structure STRING_BA_STRUCT
  before.s
  after.s
EndStructure

Procedure.i StringBeforeAndAfter(*Str,Signature.s,*StrBA.STRING_BA_STRUCT)
  Protected *src.Unicode
  Protected *sig.Unicode
  Protected *a.Unicode
  Protected *b.Unicode
  Protected *c.Unicode
  *src = *str 
  *sig = @Signature
  Repeat 
    If *src\u = *sig\u
      *a = *src
      Repeat
        *src + 2
        *sig + 2
        If *src\u <> *sig\u
          Break
        EndIf
      Until *sig\u = #Null Or *src\u = #Null
      If *sig\u = #Null 
        *b = *src - *a
        *b + *a
        *c = *a - 4
        If *a < *Str Or *b\u = #Null
          ProcedureReturn #False
        EndIf
        *a + Bool(*a\u = ' ') * 4
        *b + Bool(*b\u = ' ') * 2
        *sig = #Null
        Repeat
          *sig + Bool(*c\u & $30 = $30 And *c\u < $3A) 
          *sig + Bool(*c\u & $40 = $40 And *c\u <> $40 And *c\u < $5B)
          *sig + Bool(*c\u & $60 = $60 And *c\u <> $60 And *c\u < $7B)
          *sig + Bool(*c\u = '_')
          If *sig = #Null
            Break
          EndIf
          *c - 2
          *sig = 0 
        Until *c = *Str
        If *sig = 0
          *c + 2
        EndIf
        *a\u = #Null
        *StrBA\before = PeekS(*c,(*a - *c - (Bool(*a\u = ' ') * 2)) >> 1)
        *c = *b
        *sig = #Null
        Repeat
          *sig + Bool(*c\u & $30 = $30 And *c\u < $3A) 
          *sig + Bool(*c\u & $40 = $40 And *c\u <> $40 And *c\u < $5B)
          *sig + Bool(*c\u & $60 = $60 And *c\u <> $60 And *c\u < $7B)
          *sig + Bool(*c\u = '_')
          If *sig = #Null
            Break
          EndIf
          *c + 2
          *sig = 0 
        Until *c\u = #Null
        *StrBA\after = PeekS(*b,(*c - *b) >> 1)
        ProcedureReturn #True
      EndIf
      *sig = @Signature
      *src = *Str
    EndIf  
    *src + 2
  Until *src\u = #Null
  ProcedureReturn #False
EndProcedure

Procedure.i Main()
  Protected str1.s
  Protected str2.s
  Protected str.STRING_BA_STRUCT
  str1 = "blah blah blah word_before keyword word_after blah blah blah"
  str2 = " blah blah blah (word_before keyword word_after, blah blah blah "
  StringBeforeAndAfter(@str1,"keyword",@str)
  Debug str\before
  Debug str\after
  StringBeforeAndAfter(@str2,"keyword",@str)
  Debug str\before
  Debug str\after
  ;works with and without spaces after the keyword!
  str1 = "blah blah blah word_beforekeywordword_after blah blah blah"
  str2 = " blah blah blah (word_beforekeywordword_after, blah blah blah "
  StringBeforeAndAfter(@str1,"keyword",@str)
  Debug str\before
  Debug str\after
  StringBeforeAndAfter(@str2,"keyword",@str)
  Debug str\before
  Debug str\after
  ProcedureReturn #Null
EndProcedure

Main()

End
Allen
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Nov 10, 2021 2:05 am

Re: How to get the word_before and word_after a specific keyword from a string.

Post by Allen »

Hi,

The shortest(slow) version? idea from Olli and Oso. :wink:

Code: Select all

Keyword.s=" keyword "

string.s="blah blah blah word_before keyword word_after blah blah blah"
Debug String
Debug "Word Before : "+LTrim(ReverseString(StringField(ReverseString(StringField(String,1,Keyword)),1," ")),"(")
Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")

string.s=" blah blah blah (word_before keyword word_after, blah blah blah "
Debug String
Debug "Word Before : "+LTrim(ReverseString(StringField(ReverseString(StringField(String,1,Keyword)),1," ")),"(")
Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")
Allen

Edit:
was: Debug "Word After : "+RTrim(StringField(ReverseString(StringField(ReverseString(String),1,ReverseString(KeyWord))),1," "),",")
is : Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: How to get the word_before and word_after a specific keyword from a string.

Post by Jeromyal »

Code: Select all

Macro WordBefore(string, keyword, separator = " ")
  StringField(StringField(string, 1, keyword), CountString(StringField(string, 1, keyword), sep), sep)
EndMacro

Macro WordAfter(string, keyword, separator = " ")
  StringField(Trim(StringField(String, 2, keyword)), 1, sep)
EndMacro


string.s  = "blah blah blah word_before keyword word_after blah blah blah"
keyword.s = "keyword"
sep.s     = " "

Debug WordBefore(string, keyword, sep)
Debug WordAfter(string, keyword, sep)
Not perfect. Prone to errors.
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: How to get the word_before and word_after a specific keyword from a string.

Post by Jeromyal »

A strange way to get the word before...

Code: Select all

Macro BeforeWord(String, Keyword, Separator = " ")
  GetExtensionPart(ReplaceString(Trim(StringField(string, 1, keyword)), sep, "."))
EndMacro
okey, enough from me.
Olli
Addict
Addict
Posts: 1202
Joined: Wed May 27, 2020 12:26 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post by Olli »

:lol:

GetExtensionPart() option is very researched to do this task. I think everybody has won here, each one with a different approach.

I say a "hello" to Mijikai who shew me recently this easy method of *x.character\c and certainly who learnt it by another one again, as a humain string.

I thank infratec who knows the subject perfectly.

I say a hello too to ChrisR I often read to give an idea also[/b].

And I thank to everybody to share and share again.



I think I have a other approach. (It stays myself any teeth :mrgreen: :mrgreen: )

I imagine a search where each character is counted and referring depending its place in the string. It wastes lots of memory also, but it is quick and usable everywhere in a data base.
Post Reply