文字列をチェックして、その中の単語が複数回出現するかどうかを確認する必要があります。したがって、基本的に私は受け入れます:
「グーグルは恋をする」
しかし、私は受け入れません:
「Google は Google を愛します」または「Google は Google を愛します」など。
何か案は?これにアプローチする方法が本当にわかりません。どんな助けでも大歓迎です。
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 ソリューションがより簡潔であるだけでなく、2 倍以上高速であることを示唆しています。(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 で空でないことを確認する方がよいかどうかはわかりません。
最も簡単な方法は、各単語をループして、前のすべての単語と重複していないかどうかを確認することです。
逆参照を伴う正規表現