我需要检查一个字符串以查看其中是否有任何单词多次出现。所以基本上我会接受:
“谷歌做爱”
但我不接受:
“谷歌让谷歌爱”或“谷歌让谷歌爱谷歌”等。
有任何想法吗?真的不知道有什么方法可以解决这个问题,任何帮助将不胜感激。
基于 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;
}
试试这个:
function single_use_of_words($str) {
$words = explode(' ', $str);
$words = array_unique($words);
return implode(' ', $words);
}
不需要循环或数组:
<?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);
}
?>
<?php
$words = preg_split('\b', $string, PREG_SPLIT_NO_EMPTY);
$wordsUnique = array_unique($words);
if (count($words) != count($wordsUnique)) {
echo 'Duplicate word found!';
}
?>
正则表达式方式肯定是我的选择。
我用 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
)
关于偶数
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, , ,
这似乎相当快。有趣的是(对于所有答案)随着输入字符串的长度增加,内存使用量和所用时间如何增加。
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 中是否为非空。
最简单的方法是遍历每个单词并检查所有之前的单词是否有重复。
带有反向引用的正则表达式