Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Matching strings with RegExp 1

Status
Not open for further replies.

pixelz

Programmer
May 8, 2006
32
GB
Hi all,

This regular expression stuff does my head in. In theory I can SO understand it, but I seem to run into problems every time I try and do something even slightly complex with it.

So - I've written a little ASP app (in javascript) to take a whole bunch of feedback information out of a database (filled in by delegates of a conference) and have it displayed in a meaningful way on screen. Most of the responses were yes/no or good/bad etc, but there were some free text fields as well. I wanted to be able to print these out, but filter out non-useful comments like 'NA' or 'no comment' etc.

Before we get into the code, here's the page:
Take a look at Q16 + Q17 at the end.

What I did was to take every text entry for a particular question and run it through a function that would test against an array of possible responses I didn't want to include. Here's the function call:

Code:
while (!recSet.EOF) {
 //if dbase value not equal to bad responses then print it
 if ([B][COLOR=red]killEntry(recSet(valueToPrint))==false[/color][/B]) {
	outputString += "<div class='comments'>";
	outputString += recSet(valueToPrint);
	outputString += "</div>";
	}
	recSet.MoveNext;
 }

And this is the function killEntry() I wrote:

Code:
function killEntry(valueToTest) {
 var killValues = new Array('NA','no comment on sheet','NA','Na','no response','undefined');
 var testedIt = new Boolean;

 for(i=0; i<killValues.length; i++) {
  [b][COLOR=red]re = new RegExp("^\b"+killValues[i]+"\b$");
  testedIt = re.test(valueToTest)[/color red][/b] 
   if (testedIt==true) 
    { return true; 
      break; }
 
//Response.Write(i+" "+re+" = "+valueToTest+" = "+testedIt+"<br/>");

   }
 return false;
}

As you can see I'm attempting to use the test method to copmare the two strings (making sure to include word boundaries as well.) However, it's not picking up the matches at all. The ResponseWrite in there is to check the values as we go along, but testedIt never comes back as true, even when it blatantly is. For example, here's an excerpt from the list of results I get back:


Code:
...
 0 /^NA$/ = NA = false
 1 /^no comment on sheet$/ = NA = false
 2 /^NA$/ = NA = false
 3 /^Na$/ = NA = false
 4 /^no response$/ = NA = false
 5 /^undefined$/ = NA = false
...

As you can see from line 0 and line 2, we should be getting true returned as the pattern does match the string, but it doesn't.

Can anybody spot what I'm doing wrong? Try as I might, I just can't see to get it to match.

Thanks guys!

Pix
 
Hi

That code can be corrected in several ways :
[ul]
[li]You do not need regular expressions for that.
Code:
  testedIt = valueToTest==killValues[i];
[/li]
[li]You could check all that with one expression.
Code:
function killEntry(valueToTest) {
  return valueToTest.match(/^(NA|no comment on sheet|NA|Na|no response|undefined)$/);
}
[/li]
[li]You do not need the [tt]\b[/tt] pattern :
Code:
  re = new RegExp("^"+killValues[i]+"$");
[/li]
[li]In a [tt]String[/tt] value the [tt]\b[/tt] means a backspace character. For get [tt]\b[/tt] pattern, escape the backslash ( \ ) :
Code:
  re = new RegExp("^\\b"+killValues[i]+"\\b$");
[/li]
[/ul]

Feherke.
 
Ah, beautiful!

Have tried those and the one that seems to work the best is escaping the \b - that was probably my problem all along.

some feedback on the other solutions:

1. Sure - that's definately possible, but trying to get my head around using regular expressions so wanted to take that road.

2. This doesn't work, interestingly. Initially, I get a "Object doesn't support this poperty or method error" and when I hardcode the string datatype for valueToTest (var valueToTest = new String(valueToTest)) to make sure it's a string, nothing shows up on the output. I can click on "show details" all I want but nothing displays.

3. Yep - possibly, but I may have needed to get rid of something like "na" and I didn't want it picking up something like "inaction" for example.

4. IT WORKS! WHOOOHOO!! *GRIN*

Thanks for that Ferherke! will definately keep that in mind!

Cheers

Pix
 
Hi

Pix said:
This doesn't work, interestingly.
In fact the function I gave you works, the test condition of the [tt]if[/tt] which calls the function does not work too well together with the function.
Code:
[gray]// either make sure it returns boolean[/gray]
function killEntry(valueToTest) {
  return valueToTest.match(/^(NA|no comment on sheet|NA|Na|no response|undefined)$/)[red]?true:false[/red];

[gray]// or modify the test to accept equivalents of false[/gray]
 if ([red]![/red]killEntry(recSet(valueToPrint))) {
}
Pix said:
I may have needed to get rid of something like "na" and I didn't want it picking up something like "inaction" for example.
The pattern is already anchored to both ends of the string. So anchoring it to word boundaries does not change anything.
Code:
[blue]>>> 'na'.match(/^na$/)[/blue]
[b][[/b][red]"na"[/red][b]][/b]
[blue]>>> 'na'.match(/^inactive$/)[/blue]
[COLOR=white #888]null[/color]
[blue]>>> 'na'.match(/^\bna\b$/)[/blue]
[b][[/b][red]"na"[/red][b]][/b]
[blue]>>> 'na'.match(/^\binactive\b$/)[/blue]
[COLOR=white #888]null[/color]

Feherke.
 
the test condition of the if which calls the function does not work too well together with the function.

Ah yes - You're right. Just plugged that in and it is indeed working. Could you explain the ?true:false addendum you made there. How does that ensure the return of a boolean? is it shorthand? What would happen if you wanted to return a string for eg or an integer?

I see what you mean with the .match, but with .test isn't it the other way around? wouldn't I be doing this:

Code:
/^na$/.test('inactive')

in which case wouldn't it find the 'na' in the middle of the word? Sorry - just trying to clarify this in my own head.

Thanks for all your help!!

Pix
 
Hi

Pix said:
Could you explain the ?true:false addendum you made there.
JavaScript treats as logical false many things :
[ul]
[li][tt]false[/tt] - boolean [tt]false[/tt][/li]
[li]0 - numeric zero[/li]
[li]'' - empty [tt]String[/tt][/li]
[li]() - empty [tt]Array[/tt][/li]
[/ul]
All those can be used successfully in logical expressions. But while you explicitly compared it with [tt]false[/tt], we had to provide a boolean value.

And that ?: operator does that : returned [tt]true[/tt] is the expression evaluates to true, [tt]false[/tt] otherwise.

In many other languages usually an [tt]iif[/tt] function is available for similar expressions, which in JavaScript syntax would look like this :
Code:
[b]function[/b] iif(expression,trueValue,falseValue)
{
  [b]if[/b] (expression) [b]return[/b] trueValue;
  [b]else[/b] [b]return[/b] falseValue;
}
Hopefully the code sample explains better than me...
Pix said:
in which case wouldn't it find the 'na' in the middle of the word?
No, no need for [tt]\b[/tt] neither in that expression :
Code:
[blue]>>> /^na$/.test('inactive')[/blue]
[COLOR=#008]false[/color]
[blue]>>> /^\bna\b$/.test('inactive')[/blue]
[COLOR=#008]false[/color]
[blue]>>> /^na$/.test('na')[/blue]
[COLOR=#008]true[/color]
[blue]>>> /^\bna\b$/.test('na')[/blue]
[COLOR=#008]true[/color]

Feherke.
 
Sweet!!

Thanks for that dude!

You, as always, have been a real help!

Cheers

Pix
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top