Regex для получения строк, которые содержат только слова из списка шаблонов? - PullRequest
1 голос
/ 10 марта 2019

Рассмотрим следующие элементы массива

 1.benclinton
 2.clintonharry
 3.harryben
 4.benwill
 5.jasonsmith
 6.smithclinton

Предположим, что список шаблонов Бен, Гарри, Клинтон , тогда я должен получить результат

1.benclinton  
2.clintonharry  
3.harryben

Итак, по сути, результат должен содержать строки, содержащие только слова из списка шаблонов. Заказ не важен

Кроме того, в каждой строке будет не более двух слов. то есть Бенсмит никогда не будет делом.

Так как все мои строки находятся в массиве, я подумал об использовании preg_grep в php для этого, но меня поразило создание правильного регулярного выражения для этого.

какое регулярное выражение может достичь этого? Есть ли другой эффективный способ, кроме сопоставления регулярных выражений, который сделает эту работу?

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

Ответы [ 3 ]

3 голосов
/ 10 марта 2019

как то так

$names_list = ['benclinton','clintonharry','harryben','benwill','jasonsmith','smithclinton'];
$names = ['ben','harry','clinton'];  

$matches = preg_grep('/('.implode('|',$names).')(?1)/', $names_list);
//-  /(ben|harry|clinton)(?1)/  -- (?1) = recurse capture group 1 

print_r($matches);

выход

Array
(
    [0] => benclinton
    [1] => clintonharry
    [2] => harryben
)

Песочница

Это требует, чтобы по крайней мере два имени (даже одно и то же 2x) совпадали. Но это как бы данность в данном случае, или все будет соответствовать.

Если вы хотите быть особенно осторожным, если $names может содержать что-то важное для регулярных выражений, такое как +, *, \ и т. Д., Вы можете добавить это

$matches = preg_grep('/('.implode('|',array_map(function($name){return preg_quote($name,'/');},$names)).')(?1)/', $names_list);
0 голосов
/ 10 марта 2019

Без Regex.Do с array_filter и strpos

  1. Массив фильтров с соответствующим вторым массивом, число которых превышает 1

Песочница

<?php
$a = ['benclinton','clintonharry','harryben','benwill','jasonsmith','smithclinton'];
$a2 = ['ben','clinton','harry'];
$res = array_filter($a,function($str="") use($a2){
    $r =array_filter($a2,function($a2str) use($str){
        return strpos($str,$a2str) !== FALSE;
    });
    return count($r) > 1;
});
print_r($res);
?>
0 голосов
/ 10 марта 2019

Похоже, что вы хотите сопоставить элементы массива, которые являются точными комбинациями двух ключевых слов.Для подхода регулярных выражений мы можем попытаться взять кросс-произведение вектора ключей, а затем сгенерировать чередование.Затем мы можем использовать preg_grep против вашего входного массива, чтобы найти все подходящие элементы.

$array = array("benclinton", "clintonharry", "harryben", "benwill", "jasonsmith", "smithclinton");
$input = array("ben", "harry", "clinton");
$regex = "";
foreach ($input as $term1)  {
    foreach ($input as $term2)  {
        if ($regex != "") $regex .= "|";
        $regex .= $term1.$term2;
    }
}
$regex = "/^(" . $regex . ")$/";
$matches = preg_grep($regex, $array);
print_r($matches);

Array
(
    [0] => benclinton
    [1] => clintonharry
    [2] => harryben
)

Вот чередование регулярных выражений, сгенерированное приведенным выше сценарием:

(benben|benharry|benclinton|harryben|harryharry|harryclinton|clintonben|
    clintonharry|clintonclinton)
...