Searching a String using an Array

I’m using an array to check if any values are contained in a string. The way I’m approaching it is first replacing any matched values with a word like, “bad”, and then I’m not showing any strings that contain the word “bad”. I’ll be using this code with a ListBox, but in the example below, I’m just printing to a TextArea. If there’s a better way to approach this, I’m definitely open to ideas.

Here is some working code. The example below returns “She had bad coins”:

    dim TextArray as string = array("one","two","three")
    
    foo = "She had two coins"
    
    for each t in TextArray
      foo = replaceall(foo , t, "bad" )
      TextArea.text = foo
    next

However, when I add an if statement to check if the word “bad” is included in the string, this code returns “She had two coins”

    dim TextArray as string = array("one","two","three")
    
    foo = "She had two coins"
    
    for each t in TextArray
      foo = replaceall(foo , t, "bad" )
      if InStr(foo, "bad") = 0 then
        TextArea.text = foo
      end if
    next

What is causing foo to revert back to the pre-replaceall value?

if InStr(foo, "bad") = 0 then

should be

if InStr(foo, "bad") > 0 then

That change is giving me, “She had bad coins”, which is a step in the right direction.

I was attempting to use “= 0” to avoid printing foo if it contained the word “bad”. But using “= 0” or “< 1” simply reverts to the “Show had two coins”. Is that not possible?

in newer xojo it should be

foo = foo.ReplaceAll(t, "bad")

TextArea is not the best name for a Control, should be TextArea1 or something else.

Updated! It’s still printing “She had bad coins” when I don’t want it to print anything at all based on the match.

rework your method :wink:

Try taking the if/then outside of the for loop. Something like this:

 dim TextArray as string = array("one","two","three")
    
    foo = "She had two coins"
    
    for each t in TextArray
      foo = replaceall(foo , t, "bad" )
    next
    if InStr(foo, "bad") > 0 then
     TextArea.text = foo
   end if
1 Like

Your problem is that foo is changing, but because it now contains “bad”, you never put it back into the textarea. As soon as it changes, your test for <= 0 causes the textarea to not be updated with the modified value of foo.

Yes, like what Robert says, if you move the if outside of the for loop, it seems to work. Almost like the code is outrunning the replaceall method and reaches the InStr before ReplaceAll is done…if you move it outside it has enough time to update itself. Weird.

1 Like

The problem is that the text was replaced in the second iteration of the loop. However, on the third iteration, there is no replacement and the test is repeated. What finally appears in the text field depends only on the result of the very last test. So, there’s no point including the test in the loop.

1 Like

ohhhh I get it. It’s updating TextArea every time, and I’m only seeing the last test on “three”. Thank you for catching that, this is extremely clear now!

Actually, no. Without the IF statement, the TextArea is updated every time and you do see the results - foo doesn’t get reset, it will continue to contain “bad”. With the IF statement, the TextArea is only updated the first time. On the second and third loop, even though foo now contains “bad”, the TextArea isn’t being updated.

You need a completely different approach if you don’t want the overhead of updating the TextArea every time and/or quit once you hit the first match. I’m not really sure which you actually wanted to accomplish.

An alternate way to approach this using RegEx:

var pattern as string = String.FromArray( textArray, "\E|\Q" )
pattern = "\b(\Q" + pattern + "\E)\b"

var rx as new RegEx
rx.SearchPattern = pattern

if rx.Search( foo ) isa RegExMatch then
  // foo contains one of the words in textArray
end if

(untested)

In your example, pattern would end up as:

\b(\Qone\E|\Qtwo\E|\Qthree\E)\b

\b is a word boundary. \Q...\E tells the engine to use what’s between those literally, ignoring the meaning of otherwise-special tokens.