Список фильтров с использованием динамического регулярного выражения совпадения всего слова в дротике - PullRequest
1 голос
/ 18 апреля 2020

Я фильтрую список таким образом, но я думаю, что должен быть лучший подход для фильтрации списка внутри, где blo c, это не позволяет мне объявлять переменную. Есть ли другой способ достичь того же

var cc = contactsAll
          .where(
            (i) =>
                regularExpression(i.displayName, 'dev') ||
                regularExpression(i.displayName, 'soft') ||
                regularExpression(i.displayName, 'angular') ||
                regularExpression(i.displayName, 'java') 
          )
          .toList();

моя функция фильтра выражений

  bool regularExpression(String stringg, String search) {
    RegExp exp = new RegExp(
      "\\b" + search + "\\b",
      caseSensitive: false,
    );
    return exp.hasMatch(stringg);
  }

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 18 апреля 2020

Вы можете построить шаблон динамически:

var keys = ['dev', 'soft', 'angular', 'java'];
var regex = new RegExp("\\b(?:${keys.join('|')})\\b", caseSensitive: false);
var contactsAll = ['No match', 'I like java', 'I like javascript'];
var cc = contactsAll.where( (i) => regex.hasMatch(i) ).toList();
print(cc); // => [I like java]

Регулярное выражение будет выглядеть как \b(?:dev|soft|angular|java)\b и будет соответствовать любому из ключевых слов в группе без захвата как целое слово из-за \b границ слова . См. Демонстрационную версию regex .

Если keys может содержать специальные символы, но вам все еще нужен поиск по целому слову, вам нужно экранировать все специальные символы и использовать либо однозначный Границы

var regex = new RegExp("(?:^|\\W)(?:${keys.map((val) => val.replaceAll(new RegExp(r'[-\/\\^$*+?.()|[\]{}]'), r'\\$&')).join('|')})(?!\\w)", caseSensitive: false);

В результате получается шаблон (?:^|\W)(?:dev|soft|angular|java)(?!\w) ( см. демонстрацию ), где (?:^|\W) соответствует началу строки или несловесному символу, а для (?!\w) требуется Отсутствие слова char непосредственно справа от текущего местоположения.

.map((val) => val.replaceAll(new RegExp(r'[-\/\\^$*+?.()|[\]{}]'), r'\\$&')) part экранирует буквальную часть для использования в регулярном выражении .

или Пробельные границы :

var regex = new RegExp("(?:^|\\s)(?:${keys.map((val) => val.replaceAll(new RegExp(r'[-\/\\^$*+?.()|[\]{}]'), r'\\$&')).join('|')})(?!\\S)", caseSensitive: false);

В результате получается шаблон (?:^|\s)(?:dev|soft|angular|java)(?!\S), где (?:^|\s) соответствует началу строки или пробела, а (?!\S) требует немедленного отсутствия непробельного символа справа от текущего местоположения.

См. демонстрационную версию regex .

0 голосов
/ 18 апреля 2020

Не создавая функцию, вы можете использовать метод contains на вашем displayName следующим образом:

    var cc = contactsAll
    .where((i) =>
        i.displayName.contains(RegExp('\\bdev\\b')) ||
        i.displayName.contains(RegExp('\\bsoft\\b')) ||
        i.displayName.contains(RegExp('\\bangular\\b')) ||
        i.displayName.contains(RegExp('\\bjava\\b')),)
    .toList();
...