1

I trying to improve a textbox that filters a gridview, by implementing an enhanced textbox that can identify AND, OR, NOT operators by searching for this keywords in the string the user inputs in the textbox.

I am trying to do a regular expression to group the results but I'm not very good at this and I am failing to get what I want.

An example of what I want is as follows:

string = "build1 and build2 and build3 or build4 or not build5 and not build6"

results in a split mode:

  • build1 and
  • build2 and
  • build3 or
  • build4 or not
  • build5 and not
  • build6

This is because then I will take the first for example and replace with

SomeTable.Name_Of_Build = 'build1' AND

SomeTable.Name_Of_Build = 'build2' AND .... so on

3 Answers 3

2

This works for me

\w+(\sand\snot|\sor\snot|\sand|\sor|$)

Sign up to request clarification or add additional context in comments.

2 Comments

wow this one is great man, thanks a lot! It also respects if I add "()" to the string. But the thing is that I want to learn so, what does the $ means? Also I made a little change and have my expression like this: (\w+\sand\snot|\w+\sor\snot|\w+\sand|\w+\sor|$)
$ matches the end of the string. The () enclose match choices separated by |. The change you made should work, but is a little wasteful as you are including \w+ (match any character) in each or statement, also you haven't included it before the $ so the last match is missed.
0

I might recommend that instead of using a regular expression to group the results you do something like this. I think it would be more robust than trying to guess at the right regex.

string filter = "build1 and buil2 and build3 or build4 or not build5"
list<string> filterTokens = filter.Split(new char[] {' '})

string gridViewFilter = "";    
bool notEqual = false;

foreach(string token in filterTokens)
{
   if(token == "and")
   {
      gridViewFilter += "and"
   }
   else if(token == "or")
   {
     gridViewFilter += "or"
   }
   else if(token == "not")
   {
      notEqual = true;
   }
   else if(notEqual)
   {
      gridViewFilter += "SomeTable.Name_Of_Build <> '" + token + "'";
      notEqual = false;
   }
   else
   {
      gridViewFilter += "SomeTable.Name_Of_Build <> '" + token + "'";
   }
}

Also, if you really want to implement a robust and full featured sort you need to look into using Reverse Polish Notation (RPN). It would allow you to handle parentheses and order of operations. An RPN implementation would look something like this.

private bool CheckForFilterMatch(string filter, List<string> values, bool exactMatch)
{
    for (int i = 0; i < values.Count; i++)
    {
        values[i] = values[i].ToLower();
    }

    if (filter.Trim() == "")
    {
        return true;
    }

    List<string> rpn = GetPostFixNotation(filter);

    Stack<bool> output = new Stack<bool>();

    foreach (string token in rpn)
    {
        if (IsValue(token))
        {
            bool isMatch;
            if (exactMatch)
            {
                isMatch = values.Contains(token.ToLower());
            }
            else
            {
                isMatch = false;
                foreach (string value in values)
                {
                    isMatch = (value.IndexOf(token.ToLower()) != -1);

                    if (isMatch) break;
                }
            }

            output.Push(isMatch);
        }
        else if (IsOperator(token))
        {
            bool operand1 = output.Pop();
            bool operand2 = output.Pop();

            if (token == "&")
            {
                output.Push(operand1 && operand2);
            }
            if (token == "|")
            {
                output.Push(operand1 || operand2);
            }
        }
    }

    return output.Pop();
}


public  List<string> GetPostFixNotation(string filter)
{
    if (filter == "")
    {
        return new List<string>();
    }

    List<string> postFixNotation = new List<string>();

    Queue<string> output = new Queue<string>();
    Stack<string> operators = new Stack<string>();

    List<string> parsedFilter = ParseFilterTokens(filter);

    foreach (string token in parsedFilter)
    {
        if (IsValue(token))
        {
            output.Enqueue(token);
        }
        else if (IsOperatorNoParenth(token))
        {
            while (operators.Count > 0 && IsOperatorNoParenth(operators.Peek()))
            {
                if ((operators.Count > 0 && (Precedence(token) <= Precedence(operators.Peek()))))
                {
                    string operatorToReturn = operators.Pop();
                    output.Enqueue(operatorToReturn);
                }
                else break;
            }

            operators.Push(token);
        }
        else if (token == "(")
        {
            operators.Push(token);
        }
        else if (token == ")")
        {
            while (operators.Count > 0 && operators.Peek() != "(")
            {
                output.Enqueue(operators.Pop());
            }
            operators.Pop();
        }
    }

    while (operators.Count > 0)
    {
        output.Enqueue(operators.Pop());
    }

    while (output.Count > 0)
    {
        postFixNotation.Add(output.Dequeue());
    }

    return postFixNotation;

}

1 Comment

This is a wonderful solution as well, but I think with the first example you put here I can also respect parentheses and order of operations. I appreciate a lot your point of view as well!
0

Try this regex out:

(build[^b]+)

1 Comment

thanx for the answer but I guess i did not make my self clear. the build's words are just examples, what's important for me is the AND, OR, NOT inside the string

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.