1

私が求めているのは、アプリケーションのエンド ユーザーではなく、私自身の便宜のためであるという意味で、私は独特の状況にあります。

私は人々の IQ スコアをテストするアプリケーションを作成しようとしています (それらは無関係であり、誰にとってもあまり役に立たないことはわかっています)。

PHPでWAMPでローカルに書いています。インターネット上には、自分のプロジェクトに使用できる IQ に関する質問と回答がたくさんあることがわかりました。また、同じ質問がたくさんあることに気付きましたが、言葉遣いが少し異なります。

アプリケーションに同じ質問を「2 つ」含めるのを防ぐために利用できるサードパーティの PHP ライブラリはありますか?

「同じ」であるがプログラム的には異なる質問の例がいくつかあります。

The average of 20 numbers is zero. Of them, at the most, how many may be greater than zero?

The average of 20 numbers is zero. Of them how many may be greater than zero?

The average of 20 numbers is zero. Of them how many may be greater than zero, at the most?

明らかに、演算子を使用する PHP 自体はこれを達成できないことがわかります。質問の類似点を区別しようとする私は、私のプログラミング スキルよりもはるかに優れています。

盗作ソフトウェアを調べましたが、オープン ソースの PHP プロジェクトは見つかりませんでした。

もっと簡単な解決策はありますか?

ありがとう

** 編集 **

私が持っていたアイデアの 1 つは、すべてのスペースで質問の使用を挿入する前explodeに、結果の配列で、同じ関数が適用された他の質問と照合することでした。一致が多いほど、質問はより平等になりますか?

私は PHP の初心者ですが、これは実現可能ですか?

4

2 に答える 2

1

Levenstein Distance アルゴリズムを使用してみてください。

http://php.net/manual/en/function.levenshtein.php

同様の問題に(PHPではなくC#で)使用しましたが、非常にうまく機能します。私が見つけた秘訣は、レーベンスタイン距離を最初の文の長さ (文字数) で割ることです。これにより、質問 1 を質問 2 に変換するために必要な大まかな変化率が得られます (たとえば)。

私の経験では、50 ~ 60% 未満 (つまり、0.5 または 0.6 未満) の場合、文は同じです。高いように見えるかもしれませんが、100% が最大値ではないことに注意してください。たとえば、文字列"z"をに変換するに"abcdefghi"は、約 10 文字の変更 (レーベンシュタイン距離: 削除してzから追加abcdefghi)、または上記の計算に従って 1,000% の変更が必要です。十分な変更があれば、ランダムな文字列を他のランダムな文字列に変換できます。

于 2013-10-19T21:53:07.133 に答える
1

acfrancisが既に回答しているように、組み込みlevenshtein関数を使用するよりもはるかに簡単にはなりません。

ただし、最後の質問に答えるには、はい、あなたが提案する方法でそれを行うことは実行可能であり、それほど難しくありません.

コード

function checkQuestions($para1, $para2){
    $arr1 = array_unique(array_filter(explode(' ', preg_replace('/[^a-zA-Z0-9]/', ' ', strtolower($para1)))));
    $arr2 = array_unique(array_filter(explode(' ', preg_replace('/[^a-zA-Z0-9]/', ' ', strtolower($para2)))));

    $intersect = array_intersect($arr1, $arr2);


    $p1     = count($arr1);            //Number of words in para1
    $p2     = count($arr2);            //Number of words in para2
    $in     = count($intersect);       //Number of words in intersect
    $lowest = ($p1 < $p2) ? $p1 : $p2; //Which is smaller p1 or p2?


    return array(
        'Average'  => number_format((100 / (($p1+$p2) / 2)) * $in, 2), //Percentage the same compared to average length of questions
        'Smallest' => number_format((100 / $lowest) * $in, 2)          //Percentage the same compared to shortest question
        );
}

説明

  1. 2 つの引数を受け取る関数を定義します (引数は比較する質問です)。
  2. 入力をフィルタリングし、配列に変換します
    • 入力を小文字にするstrtolower
    • 英数字以外の文字を除外するpreg_replace
  3. フィルタリングされた文字列をスペースで分解します
  4. 作成した配列をフィルタリングします
    • 空白を削除 array_filter
    • 重複を削除array_unique
  5. 2-42 番目の質問を繰り返します
  6. 両方の配列で一致する単語を見つけて、新しい配列に移動します$intersect
  7. $p1、、$p2および3 つの配列のそれぞれの単語数をカウントします。$in
  8. パーセンテージ類似度を計算して返す

次に、同じと見なされる前に、質問がどの程度類似している必要があるかのしきい値を設定する必要があります80%

注意

  • この関数は、2 つの値の配列を返します。1 つ目は長さを 2 つの入力質問の平均と比較し、2 つ目は短い方のみを比較します。単一の値を返すように変更できます。
  • number_formatはパーセンテージに使用しました...しかし、int おそらく戻ってきても大丈夫でしょう

例 1

$question1 = 'The average of 20 numbers is zero. Of them, at the most, how many may be greater than zero?';
$question2 = 'The average of 20 numbers is zero. Of them how many may be greater than zero?';

if(checkQuestions($question1, $question2)['Average'] >= 80){
    echo "Questions are the same...";
}
else{
    echo "Questions are not the same...";
}

//Output: Questions are the same...

例 2

$para1 = 'The average of 20 numbers is zero. Of them, at the most, how many may be greater than zero?';
$para2 = 'The average of 20 numbers is zero. Of them how many may be greater than zero?';
$para3 = 'The average of 20 numbers is zero. Of them how many may be greater than zero, at the most?';

var_dump(checkQuestions($para1, $para2));
var_dump(checkQuestions($para1, $para3));
var_dump(checkQuestions($para2, $para3));

/**

Output:

array(2) {
  ["Average"]=>
  string(5) "93.33"
  ["Smallest"]=>
  string(6) "100.00"
}
array(2) {
  ["Average"]=>
  string(6) "100.00"
  ["Smallest"]=>
  string(6) "100.00"
}
array(2) {
  ["Average"]=>
  string(5) "93.33"
  ["Smallest"]=>
  string(6) "100.00"
}

*/
于 2013-10-19T23:31:53.877 に答える