Я просто знаком с регулярными выражениями, но после довольно многого чтения (и обучения довольно много), я до сих пор не смог найти хорошее решение этой проблемы.
Позвольте мне быть ясным, я понимаю, что эту конкретную проблему можно было бы лучше решить, не используя регулярные выражения, но ради краткости позвольте мне сказать, что мне нужно использовать регулярные выражения (поверьте мне, я знаю, что есть лучшие способы для решения этой проблемы).
Вот проблема. Я получил большой файл, каждая строка которого имеет ровно 4 символа.
Это регулярное выражение, которое определяет "правильные" строки:
"/^[AB][CD][EF][GH]$/m"
На английском языке каждая строка имеет либо A, либо B в позиции 0, либо C, либо D в позиции 1, либо E или F в позиции 2, либо G или H в позиции 3. Я могу предположить, что каждая строка будет ровно 4 символа.
То, что я пытаюсь сделать, дано одной из этих строк, соответствует всем другим строкам, которые содержат 2 или более общих символа.
В приведенном ниже примере предполагается следующее:
-
$line
всегда является допустимым форматом -
BigFileOfLines.txt
содержит только допустимые строки
Пример:
// Matches all other lines in string that share 2 or more characters in common
// with "$line"
function findMatchingLines($line, $subject) {
$regex = "magic regex I'm looking for here";
$matchingLines = array();
preg_match_all($regex, $subject, $matchingLines);
return $matchingLines;
}
// Example Usage
$fileContents = file_get_contents("BigFileOfLines.txt");
$matchingLines = findMatchingLines("ACFG", $fileContents);
/*
* Desired return value (Note: this is an example set, there
* could be more or less than this)
*
* BCEG
* ADFG
* BCFG
* BDFG
*/
Один из способов, которым я знаю, что будет работать, - иметь регулярное выражение, подобное следующему (следующее регулярное выражение будет работать только для "ACFG":
"/^(?:AC.{2}|.CF.|.{2}FG|A.F.|A.{2}G|.C.G)$/m"
Это работает хорошо, производительность приемлема. Меня беспокоит то, что мне приходится генерировать это на основе $line
, где я предпочел бы, чтобы он не знал, что такое конкретный параметр. Кроме того, это решение плохо масштабируется, если позже код будет изменен, чтобы соответствовать словам, 3 или более символов, или если размер каждой строки увеличивается от 4 до 16.
Просто кажется, что там что-то замечательное, что я пропускаю. Также кажется, что это может быть дублирующим вопросом, но ни один из других вопросов, на которые я смотрел, по-видимому, не затрагивает эту конкретную проблему.
Спасибо заранее!
Update:
Кажется, что норма с ответами Regex предназначена для пользователей SO просто публиковать регулярное выражение и сказать: "Это должно работать для вас".
Я думаю, что это наполовину ответ. Я действительно хочу понять регулярное выражение, поэтому, если вы можете включить в свой ответ тщательное (в пределах разумного) объяснение, почему это регулярное выражение:
- A. Работает
- В. Является наиболее эффективным (я считаю, что существует достаточное количество предположений, которые могут быть сделаны относительно строки темы, что можно сделать достаточную оптимизацию).
Конечно, если вы дадите ответ, который работает, и никто не отправит ответ * с * решением, я помечаю его как ответ:)
Обновление 2:
Спасибо всем за отличные отзывы, много полезной информации, и у многих из вас были правильные решения. Я выбрал ответ, который я сделал, потому что после выполнения тестов производительности это было лучшее решение, в среднем равное время автономной работы с другими решениями.
Причины моего одобрения:
- Приведенное регулярное выражение обеспечивает отличную масштабируемость для более длинных строк
- Регулярное выражение выглядит намного чище и легче для простых смертных, таких как я, чтобы интерпретировать.
Тем не менее, многие из них относятся к приведенным ниже ответам, а также за то, что они очень тщательно объясняют, почему их решение является лучшим. Если вы столкнулись с этим вопросом, потому что это то, что вы пытаетесь выяснить, пожалуйста, дайте им все прочитать, мне очень помогли.