سؤال

أود أن أكون قادرًا على استخدام php للبحث في مصفوفة (أو الأفضل من ذلك، عمود في جدول MySQL) لسلسلة معينة.ومع ذلك، فإن هدفي هو إرجاع السلسلة التي يعثر عليها وعدد الأحرف المطابقة (بالترتيب الصحيح) أو بطريقة أخرى لمعرفة مدى معقولية نتائج البحث، حتى أتمكن من الاستفادة من هذه المعلومات لتحديد ما إذا كان أريد عرض النتيجة العليا بشكل افتراضي أو إعطاء خيارات المستخدم للقليل من الأعلى.أعلم أنه يمكنني فعل شيء مثل

$citysearch = mysql_query("  SELECT city FROM $table WHERE city LIKE '$city' ");

لكن لا يمكنني اكتشاف طريقة لتحديد مدى دقتها.

الهدف سيكون:
أ) ابحث عن "Milwaukee" إذا كان مصطلح البحث هو "milwakee" أو شيء مشابه.
ب) إذا كان مصطلح البحث "west"، فارجع أشياء مثل "West Bend" و"Westmont".

هل يعرف أحد طريقة جيدة للقيام بذلك؟

هل كانت مفيدة؟

المحلول 2

والمزيد من البحث قادني إلى مسافة Levenshtein ثم similar_text، الذي ثبت أنه أفضل طريقة للقيام بذلك.

similar_text("input string", "match against this", $pct_accuracy);

ويقارن سلاسل ثم يوفر دقة كمتغير. تحدد المسافة Levenshtein كم حذف، إدراج، أو استبدال وظائف على حرف واحد أنها تحتاج إلى القيام به للحصول من سلسلة واحدة إلى أخرى، مع بدل لترجيح كل وظيفة مختلفة (على سبيل المثال يمكنك جعله أكثر تكلفة ليحل محل شخصية من حذف حرف). انها على ما يبدو أسرع ولكن أقل دقة من similar_text. وقد ذكر ظائف أخرى لقد قرأت في مكان آخر أن سلاسل من أقل من 10000 حرفا، وليس هناك اختلاف وظيفي في السرعة.

وانتهى بي الأمر باستخدام نسخة معدلة من شيء وجدت والعمل على انجاحه. هذا ينتهي توفير أعلى 3 النتائج (إلا في حالة وجود تطابق تام).

$input = $_POST["searchcity"];
$accuracy = 0;
$runner1acc = 0;
$runner2acc = 0;
while ($cityarr = mysql_fetch_row($allcities)) {
  $cityname = $cityarr[1];
  $cityid = $cityarr[0];
  $city = strtolower($cityname);
  $diff = similar_text($input, $city, $tempacc);

  // check for an exact match
  if ($tempacc == '100') {

    // closest word is this one (exact match)
    $closest = $cityname;
    $closestid = $cityid;
    $accuracy = 100;

    break;
  }

  if ($tempacc >= $accuracy) { // more accurate than current leader
    $runner2 = $runner1;
    $runner2id = $runner1id;
    $runner2acc = $runner1acc;
    $runner1 = $closest;
    $runner1id = $closestid;
    $runner1acc = $accuracy;
    $closest  = $cityname;
    $closestid = $cityid;
    $accuracy = $tempacc;
  }
  if (($tempacc < $accuracy)&&($tempacc >= $runner1acc)) { // new 2nd place
    $runner2 = $runner1;
    $runner2id = $runner1id;
    $runner2acc = $runner1acc;
    $runner1 = $cityname;
    $runner1id = $cityid;
    $runner1acc = $tempacc;
  }
  if (($tempacc < $runner1acc)&&($tempacc >= $runner2acc)) { // new 3rd place
    $runner2 = $cityname;
    $runner2id = $cityid;
    $runner2acc = $tempacc;
  }
}

echo "Input word: $input\n<BR>";
if ($accuracy == 100) {
  echo "Exact match found: $closestid $closest\n";
} elseif ($accuracy > 70) { // for high accuracies, assumes that it's correct
  echo "We think you meant $closestid $closest ($accuracy)\n";
} else {
  echo "Did you mean:<BR>";
  echo "$closestid $closest? ($accuracy)<BR>\n";
  echo "$runner1id $runner1 ($runner1acc)<BR>\n";
  echo "$runner2id $runner2 ($runner2acc)<BR>\n";
}

نصائح أخرى

ويجب عليك التحقق من النص الكامل تبحث في الخلية. تحقق أيضا خارج الميناء زند للمشروع أباتشي لوسين، Zend_Search_Lucene .

يمكن أن يكون هذا معقدًا للغاية، وأنا شخصيًا لست على علم بوجود أي مكتبات جيدة تابعة لجهات خارجية على الرغم من أنني متأكد من وجودها.ومع ذلك، قد يتمكن الآخرون من اقتراح بعض الحلول الجاهزة.

لقد كتبت شيئًا مشابهًا من الصفر عدة مرات في الماضي.إذا سلكت هذا الطريق، فمن المحتمل ألا يكون هذا شيئًا تريد القيام به في PHP بمفرده لأن كل استعلام سيتضمن الحصول على جميع السجلات وإجراء حساباتك عليها.من المؤكد أن الأمر سيتضمن إنشاء مجموعة من جداول الفهرس التي تلبي مواصفاتك.

على سبيل المثال ، سيتعين عليك التوصل إلى قواعد لكيفية تخيل أن "ميلووكي" قد ينتهي به الأمر إلى "ميلواكي". كان حلي لهذا هو القيام بضغط حرف العلة وضغط الازدواجية (لست متأكدًا مما إذا كانت هذه مصطلحات بحث بالفعل).لذلك، سيتم فهرسة ميلووكي على النحو التالي:

  • ميلووكي
  • m_lw__k__
  • m_lw_k_

عندما يأتي استعلام البحث عن "milwaukee"، سأجري نفس العملية على إدخال النص، ثم أجري بحثًا في جدول الفهرس عن:

SELECT cityId,
       COUNT(*)
  FROM myCityIndexTable
 WHERE term IN ('milwaukee', 'm_lw__k__', 'm_lw_k_')

عندما يأتي استعلام البحث عن "milwakee"، سأجري نفس العملية على إدخال النص، ثم أجري بحثًا في جدول الفهرس عن:

SELECT cityId,
       COUNT(*)
  FROM myCityIndexTable
 WHERE term IN ('milwaukee', 'm_lw_k__', 'm_lw_k_')

في حالة ميلووكي (مكتوبة بشكل صحيح)، فإنه سيتم إرجاع "3" للعدد.

في حالة ميلووكي (تهجئتها بشكل غير صحيح)، فإنه سيتم إرجاع "2" للعدد (نظرا لأنه لن يتطابق مع m_lw__k__ النمط لأنه يحتوي على حرف علة واحد فقط في المنتصف).

إذا قمت بفرز النتائج على أساس العدد، فسوف ينتهي بك الأمر إلى استيفاء إحدى القواعد الخاصة بك، وهي أن "ميلووكي" سيتم تصنيفها في نهاية المطاف كتطابق محتمل أعلى من "ميلووكي".

إذا كنت ترغب في بناء هذا النظام بطريقة عامة (كما تم التلميح باستخدامك لـ $table في الاستعلام) فربما تحتاج إلى جدول تعيين آخر في مكان ما هناك لتعيين المصطلحات الخاصة بك إلى الجدول المناسب.

أنا لا أقترح أن هذه هي الطريقة الأفضل (أو حتى الجيدة) للقيام بهذا الأمر، بل مجرد شيء قمت به في الماضي وقد يكون مفيدًا لك إذا كنت تخطط لمحاولة القيام بذلك دون حل من طرف ثالث.

ونتيجة معظم مجن مع مثل هذه هي واحدة "٪ رجل" هذا سوف نعود كل امرأة في الملف! في حالة الإدراج ربما حل يست سيئة للغاية هو الحفاظ على تقصير الإبرة البحث. في قضيتك مباراة سوف يأتي عندما الخاص بك البحث $ قصيرة مثل "milwa".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top