在两组或更多组文本中查找模式

时间:2013-09-15 18:18:54

标签: php pattern-matching

我需要搜索大量数据才能查找某些模式。

问题是在寻找所述模式时,我没有提到我正在寻找的东西。

或者换句话说,我有两段。每个类似的主题。我需要能够比较两个段落并找到模式。两段中的短语和两次都说过。

似乎无法找到解决方案,因为preg_match和其他功能是您提供所需内容所需的功能。

示例段落

第1段:

  蜜蜂花粉由蜜蜂制成,是幼蜂的食物。它   被认为是大自然中最完全营养的食物之一   含有人类所需的几乎所有营养素。蜜蜂采集的花粉   富含蛋白质(约40%蛋白质),游离氨基酸,   维生素,包括B-复合物和叶酸。

第2段:

  蜜蜂花粉由蜜蜂制成。这是受精所必需的   的植物。微小颗粒由50 / 1,000毫米组成   小体,形成于雄蕊中心雄蕊的自由端   开花,大自然最完全滋养的食物。各种各样的   宇宙中的花朵会喷出花粉。很多果园   水果和农作物也是如此。

从这些例子中可以看出这些模式:

  蜜蜂花粉由蜜蜂制成

  

自然界最完全营养的食物

这两个短语都出现在两个段落中。

2 个答案:

答案 0 :(得分:1)

这可能是一个复杂的问题,取决于您是否正在寻找与逐字逐句匹配的类似短语或短语。

找到准确的逐字逐句匹配非常简单,您需要做的就是将常见的中断(如标点符号)(例如.,;:)拆分,也可以在连词上拆分(例如and or)。然而,问题来自于,例如,形容词两个短语可能完全相同,但有一个单词不同,如下所示:

The world is spinnnig around its axis at a tremendous speed.
The world is spinning around its axis at a magnificent speed.

这不匹配,因为tremendousmagnificent代替彼此使用。然而,你可能会解决这个问题,这将是一个更复杂的问题。

答案

如果我们坚持简单方面,我们可以通过一些代码行来实现短语匹配(在此示例中 4 ;不包括评论/可读性的格式。)

$wordSplits = 'and or on of as'; //List of words to split on
preg_match_all('/(?<m1>.*?)([.,;:\-]| '.str_replace(' ', ' | ', trim($wordSplits)).' )/i', $para1, $matches1);
preg_match_all('/(?<m2>.*?)([.,;:\-]| '.str_replace(' ', ' | ', trim($wordSplits)).' )/i', $para2, $matches2);
$commonPhrases = array_filter( //Removes blank $key=>$value pairs
                    array_intersect( //Finds matching paterns
                        array_map(function($item){
                            return(strtolower(trim($item))); //Cleans array for $para1 values - removes leading and following spaces
                        }, $matches1['m1']),
                        array_map(function($item){
                            return(strtolower(trim($item))); //Cleans array for $para2 values - removes leading and following spaces
                        }, $matches2['m2'])
                    )
                );


var_dump($commonPhrases);
/**
OUTPUT:

array(2) {
  [0]=>
  string(31) "bee pollen is made by honeybees"
  [5]=>
  string(41) "nature's most completely nourishing foods"
}
/*

上面的代码将找到在标点符号上分割的匹配项(在[...]模式的preg_match_all中定义),它还将连接单词列表(仅匹配单词列表中的单词与前面和后面的单词空间)。

单词表

您可以更改单词列表以包含您喜欢的任何中断,编辑列表直到您获得所需的短语,例如:

$wordSplits = 'and or';
$wordSplits = 'and but if or';
$wordSplits = 'a an as and by but because if in is it of off on or';

标点符号

您可以在列表中添加您喜欢的任何标点符号([]之间),但请记住,某些字符确实有特殊含义,可能需要转义(或放置得恰当): -^应该成为\-\^,或者放置在特殊含义不起作用的位置。

您可以考虑更改:

([.,;:\-]|

要:

([.,;:\-] | //Adding a space before the pipe

这样您只能拆分后跟空格的标点符号。例如:这意味着50,000之类的项目不会被拆分。

空格和休息

您还可以考虑将空格更改为\s,以便包含tabsnewlines等,而不仅仅是空格。像这样:

'/(?<m1>.*?)([.,;:\-]|\s'.str_replace(' ', '\s|\s', trim($wordSplits)).'\s)/i'

这也适用于:

([.,;:\-]\s|

如果你决定走这条路。

答案 1 :(得分:0)

我一直在研究这段代码,不知道它是否适合您的需求......随意扩展它!

$p1 = "Bee Pollen is made by honeybees, and is the food of the young bee. It is considered one of nature's most completely nourishing foods as it contains nearly all nutrients required by humans. Bee-gathered pollens are rich in proteins (approximately 40% protein), free amino acids, vitamins, including B-complex, and folic acid.";
$p2 = "Bee Pollen is made by honeybees. It is required for the fertilization of the plant. The tiny particles consist of 50/1,000-millimeter corpuscles, formed at the free end of the stamen in the heart of the blossom, nature's most completely nourishing foods. Every variety of flower in the universe puts forth a dusting of pollen. Many orchard fruits and agricultural food crops do, too.";

// Strip strings of periods etc.
$p1 = strtolower(str_replace(array('.', ',', '(', ')'), '', $p1));
$p2 = strtolower(str_replace(array('.', ',', '(', ')'), '', $p2));

// Extract words from first paragraph
$w1 = explode(" ", $p1);

// Build search string
$search = '';
$found = array();


foreach ($w1 as $word) {
    //echo 'Word: ' . $word . "<br />";
    $search .= ' ' . $word;
    $search = trim($search);

    //echo '. . Search string: '. $search . "<br /><br />";

    if (substr_count($p2, $search)) {
        $old_search = $search;
        $num_occured = substr_count($p2, $search);
        //echo " . . . found!" . "<br /><br /><br />";
        $add = TRUE;
    } else {
        //echo " . . . not found! Generating new search string: " . $word . '<br />';
        if ($add) {
            $found[] = array('pattern' => $old_search, 'occurences' => $num_occured);
            $add = FALSE;
        }
        $old_search = '';
        $search = $word;
    }
}

print_r($found);

上面的代码从第二个字符串的第一个字符串中查找模式的出现。 我相信它可以写得更好,但是因为它已经过了午夜(当地时间),我并不像我想的那样“新鲜”...

Codepad-link