Regex "AND"

On one occasion we had a PySide QListView with a QSortFilterProxyModel and we wanted to use regex for the filtering. QSortFilterProxyModel does accept regex for filtering so we figured this wouldn’t be a problem. One of the requirements was the filtered text would be space delineated. For example, if the user typed “red blue”, it would now have 2 search terms: “red” and “blue”.

Next to the filter text box were 2 radio buttons denoting “AND” and “OR”. The user would use one of these button to let the filter know what they expect from the returned items; if the user selected “OR”, the filter would return all items found with “red”, all items found with “blue”, and all items found with both “red” and “blue”; if the user selected “AND”, the filter would ONLY return all items found with BOTH “red” and “blue”.

Lucking for us, regex supports OR right out of the box. It’s denoted by “|”.

But AND… is not. So we have to build it. The code for regex AND is:

(?=.*'first term')(?=.*'second term').*

You can use as many terms as you want as long as they’re contained in their own parentheses. So the next step would be to get all of your key words in a list and build your regex using string “join” and “format” methods.

search_strings = str(filter_text).split()

pattern = QtCore.QRegExp()
if search_strings:
    if filter_type == AND:
        # AND
        # regex pattern = (?=.*'first term')(?=.*'second term').*
        pattern = QtCore.QRegExp(
            '{}.*'.format(
                ''.join(
                    [
                        '(?=.*{})'.format(search_string)
                        for search_string in search_strings
                    ]
                )
            ),
            QtCore.Qt.CaseInsensitive
        )
    else:
        # OR
        # regex pattern = 'first term'|'second term'
        pattern = QtCore.QRegExp(
            '|'.join(search_strings),
            QtCore.Qt.CaseInsensitive,
        )

sortfilterproxy.setFilterRegExp(pattern)