2

我需要检查一个字符串以查看其中是否有任何单词多次出现。所以基本上我会接受:

“谷歌做爱”

但我不接受:

“谷歌让谷歌爱”或“谷歌让谷歌爱谷歌”等。

有任何想法吗?真的不知道有什么方法可以解决这个问题,任何帮助将不胜感激。

4

9 回答 9

5

基于 Wicked Flea 代码:

function single_use_of_words($str) {  
   $words = explode(' ', trim($str));  //Trim to prevent any extra blank
   if (count(array_unique($words)) == count($words)) {
      return true; //Same amount of words
   }   
   return false;
}
于 2009-01-08T14:58:52.887 回答
3

试试这个:

function single_use_of_words($str) {
  $words = explode(' ', $str);
  $words = array_unique($words);
  return implode(' ', $words);
}
于 2009-01-08T14:48:07.480 回答
3

不需要循环或数组:

<?php

$needle = 'cat';
$haystack = 'cat in the cat hat';

if ( occursMoreThanOnce($haystack, $needle) ) {
    echo 'Success'; 
} 

function occursMoreThanOnce($haystack, $needle) {
    return strpos($haystack, $needle) !== strrpos($haystack, $needle);
}

?>
于 2009-01-08T15:35:48.817 回答
2
<?php
$words = preg_split('\b', $string, PREG_SPLIT_NO_EMPTY);
$wordsUnique = array_unique($words);
if (count($words) != count($wordsUnique)) {
    echo 'Duplicate word found!';
}
?>
于 2009-01-08T14:55:50.567 回答
2

正则表达式方式肯定是我的选择。

我用 Veynom 的函数和正则表达式对 320 个单词的字符串做了一个小测试

function preg( $txt ) {
    return !preg_match( '/\b(\w+)\b.*?\1/', $txt );
}

这是测试

$time['preg'] = microtime( true );

for( $i = 0; $i < 1000; $i++ ) {
    preg( $txt );
}

$time['preg'] = microtime( true ) - $time['preg'];


$time['veynom-thewickedflea'] = microtime( true );

for( $i = 0; $i < 1000; $i++ ) {
    single_use_of_words( $txt );
}

$time['veynom-thewickedflea'] = microtime( true ) - $time['veynom-thewickedflea'];

print_r( $time );

这是我得到的结果

Array
(
    [preg] => 0.197616815567
    [veynom-thewickedflea] => 0.487532138824
)

这表明 RegExp 解决方案以及更简洁的解决方案速度是其两倍以上。(对于 320 个单词和 1000 次迭代的字符串)

当我运行测试超过 10 000 次迭代时,我得到

Array
(
    [preg] => 1.51235699654
    [veynom-thewickedflea] => 4.99487900734
)

非 RegExp 解决方案也使用更多的内存。

所以.. 对我来说正则表达式,因为他们有满满一罐油

编辑
我测试的文本有重复的单词,如果没有,结果可能会有所不同。我将发布另一组结果。

更新
删除重复项(现在 186 个单词),1000 次迭代的结果是:

Array
(
    [preg] => 0.235826015472
    [veynom-thewickedflea] => 0.2528860569
)

关于偶数

于 2009-01-08T23:10:43.003 回答
1
function Accept($str)
{
    $words = explode(" ", trim($str));
    $len = count($words);
    for ($i = 0; $i < $len; $i++)
    {
        for ($p = 0; $p < $len; $p++)
        {
            if ($p != $i && $words[$i] == $words[$p])
            {
                return false;
            }
        }
    }
    return true;
}

编辑

整个测试脚本。请注意,当打印“false”时,php 什么都不打印,但 true 打印为“1”。

<?php

    function Accept($str)
    {
            $words = explode(" ", trim($str));
            $len = count($words);
            for ($i = 0; $i < $len; $i++)
            {
                    for ($p = 0; $p < $len; $p++)
                    {
                            if ($p != $i && $words[$i] == $words[$p])
                            {
                                    return false;
                            }
                    }
            }
            return true;
    }

echo Accept("google makes love"), ", ", Accept("google makes google love"), ", ",
    Accept("google makes love love google"), ", ", Accept("babe health insurance babe");


?>

打印正确的输出:

1, , , 
于 2009-01-08T14:43:18.970 回答
1

这似乎相当快。有趣的是(对于所有答案)随着输入字符串的长度增加,内存使用量和所用时间如何增加。

function check($str) {
    //remove double spaces
    $c = 1;
    while ($c) $str = str_replace('  ', ' ', $str, $c);

    //split into array of words
    $words = explode(' ', $str);
    foreach ($words as $key => $word) {
        //remove current word from array
        unset($words[$key]);
        //if it still exists in the array it must be duplicated
        if (in_array($word, $words)) {
            return false;
        }
    }
    return true;
}

编辑

修复了多个空格的问题。我不确定是否最好在开始时删除这些(就像我一样)或检查每个单词在 foreach 中是否为非空。

于 2009-01-08T15:01:53.660 回答
0

最简单的方法是遍历每个单词并检查所有之前的单词是否有重复。

于 2009-01-08T14:44:06.800 回答
-1

带有反向引用的正则表达式

http://www.regular-expressions.info/php.html

http://www.regular-expressions.info/named.html

于 2009-01-08T14:44:54.177 回答