Фильтрация с использованием предиката занимает много времени - PullRequest
0 голосов
/ 25 августа 2018

У меня есть 40k строк в массиве.Я хочу отфильтровать массив, чтобы получить только совпадающие строки.У меня есть некоторые предварительные условия, например, он может иметь разделитель между ними, это должен быть поиск слов, а поиск может иметь несколько слов.Итак, я пошел с регулярным выражением, и это занимает много времени.

Ниже приведен код, который я сгенерировал только для целей представления здесь.

var arr = [String]()
for index in stride(from: 0, to: 40000, by: 1) {
    arr.append("Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.")
}

// We specify the words to be searched here
let searchTexts = ["aliqua", "Ut"]

// The time the execution started
print(Date().timeIntervalSince1970)


let predicate = NSPredicate(format: "SELF matches[cd] %@", ".*\\b\(searchTexts.joined(separator: "[ ,.!?;:\"(')-]*"))\\b.*")
let fil = arr.filter { (str) -> Bool in
    return predicate.evaluate(with: str)
}

// The time the execution stopped
print(Date().timeIntervalSince1970)

Время, затраченное на 2 секундыи в симуляторе iOS.В устройствах требуется больше.

Как улучшить регулярное выражение?Я искал много сайтов, но это мне не помогло.

Редактировать:

Вышеуказанный вопрос был изменен, поскольку в него были включены основные данные.

Мой актуальный вопрос сейчас заключается в том, как применить ту же логику к извлечению основных данных?

1 Ответ

0 голосов
/ 25 августа 2018

Не используйте метод, который требует совпадения всей строки, если все, что вам нужно, это частичное совпадение. NSPredicate с MATCHES требует полного совпадения строки, и вы должны использовать .* или подобное, чтобы гарантировать это. Однако шаблон жадных точек .* захватывает всю строку, а затем возвращает , чтобы разместить текст для последующих шаблонов. Чем больше шаблонов будет после .*, тем менее эффективным будет шаблон.

Вам необходимо использовать метод, который разрешит частичное совпадение и, следовательно, позволит вам избавиться от .*, например. range(of:options:range:locale:) при передаче опции .regularExpression.

В приведенном выше сценарии вы можете удалить let predicate = NSPredicate(format: "SELF matches[cd] %@", ".*\\b\(searchTexts.joined(separator: "[ ,.!?;:\"(')-]*"))\\b.*" и заменить return predicate.evaluate(with: str) на

return str.range(of: "\\b\(searchTexts.joined(separator: "[ ,.!?;:\"(')-]*"))\\b", options: .regularExpression) != nil

См. новую демонстрацию регулярных выражений (56 шагов) и демонстрационную версию регулярных выражений (541 шагов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...